Skip to content

Commit d2e2596

Browse files
authored
Speed up parseInt and parseUint (#112)
There's no need to check for possible overflow before we handle each byte of input. We can just handle the next byte and then check whether overflow occurred.
1 parent 42eedba commit d2e2596

File tree

1 file changed

+18
-40
lines changed

1 file changed

+18
-40
lines changed

json/parse.go

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -131,33 +131,22 @@ func (d decoder) parseInt(b []byte, t reflect.Type) (int64, []byte, error) {
131131

132132
count++
133133
} else {
134-
const max = math.MaxInt64
135-
const lim = max / 10
136-
137134
if len(b) > 1 && b[0] == '0' && '0' <= b[1] && b[1] <= '9' {
138135
return 0, b, syntaxError(b, "invalid leading character '0' in integer")
139136
}
140137

141-
for _, c := range b {
142-
if !(c >= '0' && c <= '9') {
143-
if count == 0 {
144-
b, err := d.inputError(b, t)
145-
return 0, b, err
146-
}
147-
break
148-
}
149-
x := int64(c - '0')
150-
151-
if value > lim {
152-
return 0, b, unmarshalOverflow(b, t)
153-
}
154-
155-
if value *= 10; value > (max - x) {
138+
for ; count < len(b) && b[count] >= '0' && b[count] <= '9'; count++ {
139+
x := int64(b[count] - '0')
140+
next := value*10 + x
141+
if next < value {
156142
return 0, b, unmarshalOverflow(b, t)
157143
}
144+
value = next
145+
}
158146

159-
value += x
160-
count++
147+
if count == 0 {
148+
b, err := d.inputError(b, t)
149+
return 0, b, err
161150
}
162151
}
163152

@@ -177,9 +166,6 @@ func (d decoder) parseInt(b []byte, t reflect.Type) (int64, []byte, error) {
177166

178167
// parseUint is like parseInt but for unsigned integers.
179168
func (d decoder) parseUint(b []byte, t reflect.Type) (uint64, []byte, error) {
180-
const max = math.MaxUint64
181-
const lim = max / 10
182-
183169
var value uint64
184170
var count int
185171

@@ -191,26 +177,18 @@ func (d decoder) parseUint(b []byte, t reflect.Type) (uint64, []byte, error) {
191177
return 0, b, syntaxError(b, "invalid leading character '0' in integer")
192178
}
193179

194-
for _, c := range b {
195-
if !(c >= '0' && c <= '9') {
196-
if count == 0 {
197-
b, err := d.inputError(b, t)
198-
return 0, b, err
199-
}
200-
break
201-
}
202-
x := uint64(c - '0')
203-
204-
if value > lim {
205-
return 0, b, unmarshalOverflow(b, t)
206-
}
207-
208-
if value *= 10; value > (max - x) {
180+
for ; count < len(b) && b[count] >= '0' && b[count] <= '9'; count++ {
181+
x := uint64(b[count] - '0')
182+
next := value*10 + x
183+
if next < value {
209184
return 0, b, unmarshalOverflow(b, t)
210185
}
186+
value = next
187+
}
211188

212-
value += x
213-
count++
189+
if count == 0 {
190+
b, err := d.inputError(b, t)
191+
return 0, b, err
214192
}
215193

216194
if count < len(b) {

0 commit comments

Comments
 (0)