diff --git a/common/redisclient.go b/common/redisclient.go index 2758ff8..d792cc1 100644 --- a/common/redisclient.go +++ b/common/redisclient.go @@ -6,10 +6,13 @@ package common import ( "bufio" + "bytes" + "errors" "fmt" "net" "strconv" "sync" + "unicode" ) type RedisClient struct { @@ -106,6 +109,16 @@ func isError(line []byte) error { return nil } +// parseSize is a cheaper replacement for fmt.Sscanf(string(line), "$%d\r\n", &size). +func parseSize(line []byte) (int, error) { + if len(line) < 1 || line[0] != '$' { + return 0, errors.New("Missing '$' at begin of line") + } + line = bytes.TrimFunc(line[1:], unicode.IsSpace) + v, err := strconv.ParseInt(string(line), 10, 0) + return int(v), err +} + func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) { var line []byte if line, err = client.reader.ReadBytes('\n'); err != nil { @@ -114,10 +127,7 @@ func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) { if err = isError(line); err != nil { return } - if _, err = fmt.Sscanf(string(line), "$%d\r\n", &size); err != nil { - return - } - if size <= 0 { + if size, err = parseSize(line); err != nil || size <= 0 { return } if cap(*data) < size { @@ -158,7 +168,7 @@ func (client *RedisClient) QueryCuboid(cuboid Cuboid, fn func(*Block)) (err erro return } block.Coord = PlainToCoord(key) - if size, err = client.readBulkString(&data); err != nil { + if size, err = client.readBulkString(&data); err != nil || size < 0 { return } block.Data = data[0:size]