Browse Source

parse headers with or without a cas id (for kestrel, etc)

Dietrich Featherston 12 years ago
parent
commit
fed7323a51
1 changed files with 18 additions and 6 deletions
  1. 18 6
      memcache/memcache.go

+ 18 - 6
memcache/memcache.go

@@ -98,6 +98,7 @@ func legalKey(key string) bool {
 
 var (
 	crlf            = []byte("\r\n")
+	space           = []byte(" ")
 	resultStored    = []byte("STORED\r\n")
 	resultNotStored = []byte("NOT_STORED\r\n")
 	resultExists    = []byte("EXISTS\r\n")
@@ -403,15 +404,10 @@ func parseGetResponse(r *bufio.Reader, cb func(*Item)) error {
 			return nil
 		}
 		it := new(Item)
-		var size int
-		n, err := fmt.Sscanf(string(line), "VALUE %s %d %d %d\r\n",
-			&it.Key, &it.Flags, &size, &it.casid)
+		size, err := scanGetResponseLine(line, it)
 		if err != nil {
 			return err
 		}
-		if n != 4 {
-			return fmt.Errorf("memcache: unexpected line in get response: %q", string(line))
-		}
 		it.Value, err = ioutil.ReadAll(io.LimitReader(r, int64(size)+2))
 		if err != nil {
 			return err
@@ -425,6 +421,22 @@ func parseGetResponse(r *bufio.Reader, cb func(*Item)) error {
 	panic("unreached")
 }
 
+// scanGetResponseLine populates it and returns the declared size of the item.
+// It does not read the bytes of the item.
+func scanGetResponseLine(line []byte, it *Item) (size int, err error) {
+	pattern := "VALUE %s %d %d %d\r\n"
+	dest := []interface{}{&it.Key, &it.Flags, &size, &it.casid}
+	if bytes.Count(line, space) == 3 {
+		pattern = "VALUE %s %d %d\r\n"
+		dest = dest[:3]
+	}
+	n, err := fmt.Sscanf(string(line), pattern, dest...)
+	if err != nil || n != len(dest) {
+		return -1, fmt.Errorf("memcache: unexpected line in get response: %q", line)
+	}
+	return size, nil
+}
+
 // Set writes the given item, unconditionally.
 func (c *Client) Set(item *Item) error {
 	return c.onItem(item, (*Client).set)