aboutsummaryrefslogtreecommitdiff
path: root/internal/encoding/json/decode_number.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/encoding/json/decode_number.go')
-rw-r--r--internal/encoding/json/decode_number.go254
1 files changed, 0 insertions, 254 deletions
diff --git a/internal/encoding/json/decode_number.go b/internal/encoding/json/decode_number.go
deleted file mode 100644
index 2999d713..00000000
--- a/internal/encoding/json/decode_number.go
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package json
-
-import (
- "bytes"
- "strconv"
-)
-
-// parseNumber reads the given []byte for a valid JSON number. If it is valid,
-// it returns the number of bytes. Parsing logic follows the definition in
-// https://tools.ietf.org/html/rfc7159#section-6, and is based off
-// encoding/json.isValidNumber function.
-func parseNumber(input []byte) (int, bool) {
- var n int
-
- s := input
- if len(s) == 0 {
- return 0, false
- }
-
- // Optional -
- if s[0] == '-' {
- s = s[1:]
- n++
- if len(s) == 0 {
- return 0, false
- }
- }
-
- // Digits
- switch {
- case s[0] == '0':
- s = s[1:]
- n++
-
- case '1' <= s[0] && s[0] <= '9':
- s = s[1:]
- n++
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- n++
- }
-
- default:
- return 0, false
- }
-
- // . followed by 1 or more digits.
- if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
- s = s[2:]
- n += 2
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- n++
- }
- }
-
- // 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:]
- n++
- if s[0] == '+' || s[0] == '-' {
- s = s[1:]
- n++
- if len(s) == 0 {
- return 0, false
- }
- }
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- n++
- }
- }
-
- // Check that next byte is a delimiter or it is at the end.
- if n < len(input) && isNotDelim(input[n]) {
- return 0, false
- }
-
- return n, true
-}
-
-// numberParts is the result of parsing out a valid JSON number. It contains
-// the parts of a number. The parts are used for integer conversion.
-type numberParts struct {
- neg bool
- intp []byte
- frac []byte
- exp []byte
-}
-
-// parseNumber constructs numberParts from given []byte. The logic here is
-// similar to consumeNumber above with the difference of having to construct
-// numberParts. The slice fields in numberParts are subslices of the input.
-func parseNumberParts(input []byte) (numberParts, bool) {
- var neg bool
- var intp []byte
- var frac []byte
- var exp []byte
-
- s := input
- if len(s) == 0 {
- return numberParts{}, false
- }
-
- // Optional -
- if s[0] == '-' {
- neg = true
- s = s[1:]
- if len(s) == 0 {
- return numberParts{}, false
- }
- }
-
- // Digits
- switch {
- case s[0] == '0':
- // Skip first 0 and no need to store.
- s = s[1:]
-
- case '1' <= s[0] && s[0] <= '9':
- intp = s
- n := 1
- s = s[1:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- n++
- }
- intp = intp[:n]
-
- default:
- return numberParts{}, false
- }
-
- // . followed by 1 or more digits.
- if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
- frac = s[1:]
- n := 1
- s = s[2:]
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- n++
- }
- frac = frac[:n]
- }
-
- // 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:]
- exp = s
- n := 0
- if s[0] == '+' || s[0] == '-' {
- s = s[1:]
- n++
- if len(s) == 0 {
- return numberParts{}, false
- }
- }
- for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
- s = s[1:]
- n++
- }
- exp = exp[:n]
- }
-
- return numberParts{
- neg: neg,
- intp: intp,
- frac: bytes.TrimRight(frac, "0"), // Remove unnecessary 0s to the right.
- exp: exp,
- }, true
-}
-
-// normalizeToIntString returns an integer string in normal form without the
-// E-notation for given numberParts. It will return false if it is not an
-// integer or if the exponent exceeds than max/min int value.
-func normalizeToIntString(n numberParts) (string, bool) {
- intpSize := len(n.intp)
- fracSize := len(n.frac)
-
- if intpSize == 0 && fracSize == 0 {
- return "0", true
- }
-
- var exp int
- if len(n.exp) > 0 {
- i, err := strconv.ParseInt(string(n.exp), 10, 32)
- if err != nil {
- return "", false
- }
- exp = int(i)
- }
-
- var num []byte
- if exp >= 0 {
- // For positive E, shift fraction digits into integer part and also pad
- // with zeroes as needed.
-
- // If there are more digits in fraction than the E value, then the
- // number is not an integer.
- if fracSize > exp {
- return "", false
- }
-
- // Make sure resulting digits are within max value limit to avoid
- // unnecessarily constructing a large byte slice that may simply fail
- // later on.
- const maxDigits = 20 // Max uint64 value has 20 decimal digits.
- if intpSize+exp > maxDigits {
- return "", false
- }
-
- // Set cap to make a copy of integer part when appended.
- num = n.intp[:len(n.intp):len(n.intp)]
- num = append(num, n.frac...)
- for i := 0; i < exp-fracSize; i++ {
- num = append(num, '0')
- }
- } else {
- // For negative E, shift digits in integer part out.
-
- // If there are fractions, then the number is not an integer.
- if fracSize > 0 {
- return "", false
- }
-
- // index is where the decimal point will be after adjusting for negative
- // exponent.
- index := intpSize + exp
- if index < 0 {
- return "", false
- }
-
- num = n.intp
- // If any of the digits being shifted to the right of the decimal point
- // is non-zero, then the number is not an integer.
- for i := index; i < intpSize; i++ {
- if num[i] != '0' {
- return "", false
- }
- }
- num = num[:index]
- }
-
- if n.neg {
- return "-" + string(num), true
- }
- return string(num), true
-}