Browse Source

goprotobuf: Be more liberal in text format string parsing.

Also, a minor style tweak in CompactTextString.

R=r
CC=golang-dev
http://codereview.appspot.com/5876069
David Symonds 14 years ago
parent
commit
183124e64e
3 changed files with 21 additions and 4 deletions
  1. 2 2
      proto/text.go
  2. 10 2
      proto/text_parser.go
  3. 9 0
      proto/text_parser_test.go

+ 2 - 2
proto/text.go

@@ -463,7 +463,7 @@ func CompactText(w io.Writer, pb interface{}) { marshalText(w, pb, true) }
 
 
 // CompactTextString is the same as CompactText, but returns the string directly.
 // CompactTextString is the same as CompactText, but returns the string directly.
 func CompactTextString(pb interface{}) string {
 func CompactTextString(pb interface{}) string {
-	buf := new(bytes.Buffer)
-	marshalText(buf, pb, true)
+	var buf bytes.Buffer
+	marshalText(&buf, pb, true)
 	return buf.String()
 	return buf.String()
 }
 }

+ 10 - 2
proto/text_parser.go

@@ -38,6 +38,7 @@ import (
 	"fmt"
 	"fmt"
 	"reflect"
 	"reflect"
 	"strconv"
 	"strconv"
+	"strings"
 )
 )
 
 
 type ParseError struct {
 type ParseError struct {
@@ -168,8 +169,7 @@ func (p *textParser) advance() {
 			p.errorf("unmatched quote")
 			p.errorf("unmatched quote")
 			return
 			return
 		}
 		}
-		// TODO: Should be UnquoteC.
-		unq, err := strconv.Unquote(p.s[0 : i+1])
+		unq, err := unquoteC(p.s[0 : i+1])
 		if err != nil {
 		if err != nil {
 			p.errorf("invalid quoted string %v", p.s[0:i+1])
 			p.errorf("invalid quoted string %v", p.s[0:i+1])
 			return
 			return
@@ -190,6 +190,14 @@ func (p *textParser) advance() {
 	p.offset += len(p.cur.value)
 	p.offset += len(p.cur.value)
 }
 }
 
 
+func unquoteC(s string) (string, error) {
+	// A notable divergence between quoted string literals in Go
+	// and what is acceptable for text format protocol buffers:
+	// the former considers \' invalid, but the latter considers it valid.
+	s = strings.Replace(s, `\'`, "'", -1)
+	return strconv.Unquote(s)
+}
+
 // Back off the parser by one token. Can only be done between calls to next().
 // Back off the parser by one token. Can only be done between calls to next().
 // It makes the next advance() a no-op.
 // It makes the next advance() a no-op.
 func (p *textParser) back() { p.backed = true }
 func (p *textParser) back() { p.backed = true }

+ 9 - 0
proto/text_parser_test.go

@@ -92,6 +92,15 @@ var unMarshalTextTests = []UnmarshalTextTest{
 		},
 		},
 	},
 	},
 
 
+	// Quoted string with escaped apostrophe
+	{
+		in: `count:42 name: "HOLIDAY - New Year\'s Day"`,
+		out: &MyMessage{
+			Count: Int32(42),
+			Name:  String("HOLIDAY - New Year's Day"),
+		},
+	},
+
 	// Bad quoted string
 	// Bad quoted string
 	{
 	{
 		in:  `inner: < host: "\0" >` + "\n",
 		in:  `inner: < host: "\0" >` + "\n",