aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <m.shulhan@gmail.com>2022-08-26 21:48:21 +0700
committerShulhan <m.shulhan@gmail.com>2023-02-18 16:15:58 +0700
commit02b962186be4ed9597df5fc526ef85b2e66cf55b (patch)
tree593821d82e835946f306ee9f61a3b666fc387f8a
parent169203f3ee022abf66647abc99fd483fd10f9a54 (diff)
downloadgo-json-isValidNumber.tar.xz
encoding/json: optimize isValidNumber functionjson-isValidNumber
We use an index instead of reslicing the string because reslicing a string updates both the data and length fields instead of just the one index variable. Benchmark result, name old time/op new time/op delta NumberIsValid-8 19.0ns ± 0% 14.5ns ± 1% -23.70% (p=0.008 n=5+5) name old alloc/op new alloc/op delta NumberIsValid-8 0.00B 0.00B ~ (all equal) name old allocs/op new allocs/op delta NumberIsValid-8 0.00 0.00 ~ (all equal) Change-Id: I4698c5db134998f83ff47fb3add6a04ba6ec3aa0
-rw-r--r--src/encoding/json/encode.go50
1 files changed, 28 insertions, 22 deletions
diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go
index 9d59b0ff2b..da936173da 100644
--- a/src/encoding/json/encode.go
+++ b/src/encoding/json/encode.go
@@ -652,14 +652,20 @@ func isValidNumber(s string) bool {
// See https://tools.ietf.org/html/rfc7159#section-6
// and https://www.json.org/img/number.png
- if s == "" {
+ if len(s) == 0 {
return false
}
+ // We use an index instead of reslicing the string because
+ // reslicing a string updates both the data and length fields
+ // instead of just the one index variable.
+
+ var i int
+
// Optional -
- if s[0] == '-' {
- s = s[1:]
- if s == "" {
+ if s[i] == '-' {
+ i++
+ if len(s) == i {
return false
}
}
@@ -669,41 +675,41 @@ func isValidNumber(s string) bool {
default:
return false
- case s[0] == '0':
- s = s[1:]
+ case s[i] == '0':
+ i++
- case '1' <= s[0] && s[0] <= '9':
- s = s[1:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
+ case '1' <= s[i] && s[i] <= '9':
+ i++
+ for len(s) > i && '0' <= s[i] && s[i] <= '9' {
+ i++
}
}
// . followed by 1 or more digits.
- if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
- s = s[2:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
+ if len(s)-i >= 2 && s[i] == '.' && '0' <= s[i+1] && s[i+1] <= '9' {
+ i += 2
+ for len(s) > i && '0' <= s[i] && s[i] <= '9' {
+ i++
}
}
// e or E followed by an optional - or + and
// 1 or more digits.
- if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
- s = s[1:]
- if s[0] == '+' || s[0] == '-' {
- s = s[1:]
- if s == "" {
+ if len(s)-i >= 2 && (s[i] == 'e' || s[i] == 'E') {
+ i++
+ if s[i] == '+' || s[i] == '-' {
+ i++
+ if len(s) == i {
return false
}
}
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
+ for len(s) > i && '0' <= s[i] && s[i] <= '9' {
+ i++
}
}
// Make sure we are at the end.
- return s == ""
+ return len(s) == i
}
func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {