ledisdb/server/util.go

125 lines
2.1 KiB
Go
Raw Normal View History

2014-06-09 13:23:32 +04:00
package server
import (
"bufio"
"errors"
2014-10-28 12:58:37 +03:00
"fmt"
"io"
2014-06-09 13:23:32 +04:00
)
var (
2014-10-23 09:34:27 +04:00
errLineFormat = errors.New("bad response line format")
2014-06-09 13:23:32 +04:00
)
2014-07-11 06:43:39 +04:00
func ReadLine(rb *bufio.Reader) ([]byte, error) {
2014-06-09 13:23:32 +04:00
p, err := rb.ReadSlice('\n')
if err != nil {
return nil, err
}
i := len(p) - 2
if i < 0 || p[i] != '\r' {
return nil, errLineFormat
}
2014-10-28 12:58:37 +03:00
2014-06-09 13:23:32 +04:00
return p[:i], nil
}
2014-10-28 12:58:37 +03:00
func readBytes(br *bufio.Reader) (bytes []byte, err error) {
size, err := readLong(br)
if err != nil {
return nil, err
}
if size == -1 {
return nil, nil
}
if size < 0 {
return nil, errors.New("Invalid size: " + fmt.Sprint("%d", size))
}
buf := make([]byte, size+2)
if _, err = io.ReadFull(br, buf); err != nil {
return nil, err
}
if buf[len(buf)-2] != '\r' && buf[len(buf)-1] != '\n' {
return nil, errors.New("bad bulk string format")
}
bytes = buf[0 : len(buf)-2]
return
}
func readLong(in *bufio.Reader) (result int64, err error) {
read, err := in.ReadByte()
if err != nil {
return -1, err
}
var sign int
if read == '-' {
read, err = in.ReadByte()
if err != nil {
return -1, err
}
sign = -1
} else {
sign = 1
}
var number int64
for number = 0; err == nil; read, err = in.ReadByte() {
if read == '\r' {
read, err = in.ReadByte()
if err != nil {
return -1, err
}
if read == '\n' {
return number * int64(sign), nil
} else {
return -1, errors.New("Bad line ending")
}
}
value := read - '0'
if value >= 0 && value < 10 {
number *= 10
number += int64(value)
} else {
return -1, errors.New("Invalid digit")
}
}
return -1, err
}
2014-10-29 04:11:22 +03:00
func ReadRequest(in *bufio.Reader) ([][]byte, error) {
code, err := in.ReadByte()
if err != nil {
return nil, err
}
if code != '*' {
return nil, errReadRequest
}
var nparams int64
if nparams, err = readLong(in); err != nil {
return nil, err
} else if nparams <= 0 {
return nil, errReadRequest
}
req := make([][]byte, nparams)
for i := range req {
if code, err = in.ReadByte(); err != nil {
return nil, err
} else if code != '$' {
return nil, errReadRequest
}
if req[i], err = readBytes(in); err != nil {
return nil, err
}
}
return req, nil
}