diff options
| author | Shulhan <m.shulhan@gmail.com> | 2022-08-26 21:48:21 +0700 |
|---|---|---|
| committer | Shulhan <m.shulhan@gmail.com> | 2023-02-18 16:15:58 +0700 |
| commit | 02b962186be4ed9597df5fc526ef85b2e66cf55b (patch) | |
| tree | 593821d82e835946f306ee9f61a3b666fc387f8a | |
| parent | 169203f3ee022abf66647abc99fd483fd10f9a54 (diff) | |
| download | go-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.go | 50 |
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) { |
