aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/string.go
diff options
context:
space:
mode:
authorMartin Möhrmann <martisch@uos.de>2016-10-30 01:54:19 +0200
committerBrad Fitzpatrick <bradfitz@golang.org>2016-11-01 14:04:39 +0000
commitd7b34d5f29324d77fad572676f0ea139556235e0 (patch)
tree25897e07f5b4624487d4384691ab758571faebff /src/runtime/string.go
parent40aaf283124de44d513ca086976194f0133faa82 (diff)
downloadgo-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.go63
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