aboutsummaryrefslogtreecommitdiff
path: root/bytesconv.go
diff options
context:
space:
mode:
authorGravatar Aliaksandr Valialkin <valyala@gmail.com> 2016-03-30 20:49:09 +0300
committerGravatar Aliaksandr Valialkin <valyala@gmail.com> 2016-03-30 20:49:09 +0300
commit9946a8145ec0f6a2c640766f43ab34c74e66b460 (patch)
treec52a68a94405fa3749361c95d48f46efc134503f /bytesconv.go
parentscalability improvement: use per-server peripconn pool (diff)
downloadfasthttp-9946a8145ec0f6a2c640766f43ab34c74e66b460.tar.gz
fasthttp-9946a8145ec0f6a2c640766f43ab34c74e66b460.tar.bz2
fasthttp-9946a8145ec0f6a2c640766f43ab34c74e66b460.zip
bytesconv: reduce memory allocations on parse errors by using static errors
Diffstat (limited to 'bytesconv.go')
-rw-r--r--bytesconv.go43
1 files changed, 32 insertions, 11 deletions
diff --git a/bytesconv.go b/bytesconv.go
index ceef721..cb45429 100644
--- a/bytesconv.go
+++ b/bytesconv.go
@@ -3,6 +3,7 @@ package fasthttp
import (
"bufio"
"bytes"
+ "errors"
"fmt"
"io"
"math"
@@ -138,15 +139,22 @@ func AppendUint(dst []byte, n int) []byte {
func ParseUint(buf []byte) (int, error) {
v, n, err := parseUintBuf(buf)
if n != len(buf) {
- return -1, fmt.Errorf("only %d bytes out of %d bytes exhausted when parsing int %q", n, len(buf), buf)
+ return -1, errUnexpectedTrailingChar
}
return v, err
}
+var (
+ errEmptyInt = errors.New("empty integer")
+ errUnexpectedFirstChar = errors.New("unexpected first char found. Expecting 0-9")
+ errUnexpectedTrailingChar = errors.New("unexpected traling char found. Expecting 0-9")
+ errTooLongInt = errors.New("too long int")
+)
+
func parseUintBuf(b []byte) (int, int, error) {
n := len(b)
if n == 0 {
- return -1, 0, fmt.Errorf("empty integer")
+ return -1, 0, errEmptyInt
}
v := 0
for i := 0; i < n; i++ {
@@ -154,22 +162,30 @@ func parseUintBuf(b []byte) (int, int, error) {
k := c - '0'
if k > 9 {
if i == 0 {
- return -1, i, fmt.Errorf("unexpected first char %c. Expected 0-9", c)
+ return -1, i, errUnexpectedFirstChar
}
return v, i, nil
}
if i >= maxIntChars {
- return -1, i, fmt.Errorf("too long int %q", b[:i+1])
+ return -1, i, errTooLongInt
}
v = 10*v + int(k)
}
return v, n, nil
}
+var (
+ errEmptyFloat = errors.New("empty float number")
+ errDuplicateFloatPoint = errors.New("duplicate point found in float number")
+ errUnexpectedFloatEnd = errors.New("unexpected end of float number")
+ errInvalidFloatExponent = errors.New("invalid float number exponent")
+ errUnexpectedFloatChar = errors.New("unexpected char found in float number")
+)
+
// ParseUfloat parses unsigned float from buf.
func ParseUfloat(buf []byte) (float64, error) {
if len(buf) == 0 {
- return -1, fmt.Errorf("empty float number")
+ return -1, errEmptyFloat
}
b := buf
var v uint64
@@ -179,14 +195,14 @@ func ParseUfloat(buf []byte) (float64, error) {
if c < '0' || c > '9' {
if c == '.' {
if pointFound {
- return -1, fmt.Errorf("duplicate point found in %q", buf)
+ return -1, errDuplicateFloatPoint
}
pointFound = true
continue
}
if c == 'e' || c == 'E' {
if i+1 >= len(b) {
- return -1, fmt.Errorf("unexpected end of float after %c. num=%q", c, buf)
+ return -1, errUnexpectedFloatEnd
}
b = b[i+1:]
minus := -1
@@ -201,11 +217,11 @@ func ParseUfloat(buf []byte) (float64, error) {
}
vv, err := ParseUint(b)
if err != nil {
- return -1, fmt.Errorf("cannot parse exponent part of %q: %s", buf, err)
+ return -1, errInvalidFloatExponent
}
return float64(v) * offset * math.Pow10(minus*int(vv)), nil
}
- return -1, fmt.Errorf("unexpected char found %c in %q", c, buf)
+ return -1, errUnexpectedFloatChar
}
v = 10*v + uint64(c-'0')
if pointFound {
@@ -215,6 +231,11 @@ func ParseUfloat(buf []byte) (float64, error) {
return float64(v) * offset, nil
}
+var (
+ errEmptyHexNum = errors.New("empty hex number")
+ errTooLargeHexNum = errors.New("too large hex number")
+)
+
func readHexInt(r *bufio.Reader) (int, error) {
n := 0
i := 0
@@ -230,13 +251,13 @@ func readHexInt(r *bufio.Reader) (int, error) {
k = hexbyte2int(c)
if k < 0 {
if i == 0 {
- return -1, fmt.Errorf("cannot read hex num from empty string")
+ return -1, errEmptyHexNum
}
r.UnreadByte()
return n, nil
}
if i >= maxHexIntChars {
- return -1, fmt.Errorf("cannot read hex num with more than %d digits", maxHexIntChars)
+ return -1, errTooLargeHexNum
}
n = (n << 4) | k
i++