aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-07-22 18:15:38 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-07-22 18:15:38 +0000
commit22b955cca564a9a3a5b8c9d9dd1e295b7943c128 (patch)
treeabdbd898676e1f853fca2d7e031d105d7ebcf676 /libgo/go/encoding
parent9d04a3af4c6491536badf6bde9707c907e4d196b (diff)
downloadgcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.zip
gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.tar.gz
gcc-22b955cca564a9a3a5b8c9d9dd1e295b7943c128.tar.bz2
libgo: update to go1.7rc3
Reviewed-on: https://go-review.googlesource.com/25150 From-SVN: r238662
Diffstat (limited to 'libgo/go/encoding')
-rw-r--r--libgo/go/encoding/ascii85/ascii85.go6
-rw-r--r--libgo/go/encoding/asn1/asn1.go7
-rw-r--r--libgo/go/encoding/asn1/asn1_test.go4
-rw-r--r--libgo/go/encoding/asn1/marshal.go8
-rw-r--r--libgo/go/encoding/base32/base32.go10
-rw-r--r--libgo/go/encoding/base32/base32_test.go2
-rw-r--r--libgo/go/encoding/base64/base64.go12
-rw-r--r--libgo/go/encoding/base64/base64_test.go47
-rw-r--r--libgo/go/encoding/binary/binary.go24
-rw-r--r--libgo/go/encoding/binary/binary_test.go41
-rw-r--r--libgo/go/encoding/binary/varint.go2
-rw-r--r--libgo/go/encoding/csv/reader.go71
-rw-r--r--libgo/go/encoding/csv/writer.go32
-rw-r--r--libgo/go/encoding/encoding.go2
-rw-r--r--libgo/go/encoding/gob/codec_test.go6
-rw-r--r--libgo/go/encoding/gob/debug.go6
-rw-r--r--libgo/go/encoding/gob/decode.go24
-rw-r--r--libgo/go/encoding/gob/decoder.go10
-rw-r--r--libgo/go/encoding/gob/doc.go9
-rw-r--r--libgo/go/encoding/gob/encode.go20
-rw-r--r--libgo/go/encoding/gob/encoder.go6
-rw-r--r--libgo/go/encoding/gob/encoder_test.go92
-rw-r--r--libgo/go/encoding/gob/error.go4
-rw-r--r--libgo/go/encoding/gob/gobencdec_test.go8
-rw-r--r--libgo/go/encoding/gob/type.go18
-rw-r--r--libgo/go/encoding/hex/hex.go4
-rw-r--r--libgo/go/encoding/json/bench_test.go6
-rw-r--r--libgo/go/encoding/json/decode.go78
-rw-r--r--libgo/go/encoding/json/decode_test.go365
-rw-r--r--libgo/go/encoding/json/encode.go263
-rw-r--r--libgo/go/encoding/json/encode_test.go127
-rw-r--r--libgo/go/encoding/json/indent.go2
-rw-r--r--libgo/go/encoding/json/number_test.go2
-rw-r--r--libgo/go/encoding/json/scanner.go4
-rw-r--r--libgo/go/encoding/json/scanner_test.go2
-rw-r--r--libgo/go/encoding/json/stream.go56
-rw-r--r--libgo/go/encoding/json/stream_test.go68
-rw-r--r--libgo/go/encoding/json/tagkey_test.go2
-rw-r--r--libgo/go/encoding/json/tags_test.go2
-rw-r--r--libgo/go/encoding/pem/pem.go2
-rw-r--r--libgo/go/encoding/xml/marshal.go25
-rw-r--r--libgo/go/encoding/xml/read.go20
-rw-r--r--libgo/go/encoding/xml/typeinfo.go2
-rw-r--r--libgo/go/encoding/xml/xml.go17
-rw-r--r--libgo/go/encoding/xml/xml_test.go8
45 files changed, 1135 insertions, 391 deletions
diff --git a/libgo/go/encoding/ascii85/ascii85.go b/libgo/go/encoding/ascii85/ascii85.go
index 4d71938..d42eb0a 100644
--- a/libgo/go/encoding/ascii85/ascii85.go
+++ b/libgo/go/encoding/ascii85/ascii85.go
@@ -20,7 +20,7 @@ import (
//
// The encoding handles 4-byte chunks, using a special encoding
// for the last fragment, so Encode is not appropriate for use on
-// individual blocks of a large data stream. Use NewEncoder() instead.
+// individual blocks of a large data stream. Use NewEncoder() instead.
//
// Often, ascii85-encoded data is wrapped in <~ and ~> symbols.
// Encode does not add these.
@@ -85,7 +85,7 @@ func Encode(dst, src []byte) int {
// MaxEncodedLen returns the maximum length of an encoding of n source bytes.
func MaxEncodedLen(n int) int { return (n + 3) / 4 * 5 }
-// NewEncoder returns a new ascii85 stream encoder. Data written to
+// NewEncoder returns a new ascii85 stream encoder. Data written to
// the returned writer will be encoded and then written to w.
// Ascii85 encodings operate in 32-bit blocks; when finished
// writing, the caller must Close the returned encoder to flush any
@@ -294,7 +294,7 @@ func (d *decoder) Read(p []byte) (n int, err error) {
}
}
- // Out of input, out of decoded output. Check errors.
+ // Out of input, out of decoded output. Check errors.
if d.err != nil {
return 0, d.err
}
diff --git a/libgo/go/encoding/asn1/asn1.go b/libgo/go/encoding/asn1/asn1.go
index 8bafefd..2b5ad08 100644
--- a/libgo/go/encoding/asn1/asn1.go
+++ b/libgo/go/encoding/asn1/asn1.go
@@ -393,7 +393,7 @@ func isPrintable(b byte) bool {
// byte slice and returns it.
func parseIA5String(bytes []byte) (ret string, err error) {
for _, b := range bytes {
- if b >= 0x80 {
+ if b >= utf8.RuneSelf {
err = SyntaxError{"IA5String contains invalid character"}
return
}
@@ -461,6 +461,11 @@ func parseTagAndLength(bytes []byte, initOffset int) (ret tagAndLength, offset i
if err != nil {
return
}
+ // Tags should be encoded in minimal form.
+ if ret.tag < 0x1f {
+ err = SyntaxError{"non-minimal tag"}
+ return
+ }
}
if offset >= len(bytes) {
err = SyntaxError{"truncated tag or length"}
diff --git a/libgo/go/encoding/asn1/asn1_test.go b/libgo/go/encoding/asn1/asn1_test.go
index e0e8331..f8623fa 100644
--- a/libgo/go/encoding/asn1/asn1_test.go
+++ b/libgo/go/encoding/asn1/asn1_test.go
@@ -364,7 +364,7 @@ var tagAndLengthData = []tagAndLengthTest{
{[]byte{0xa0, 0x01}, true, tagAndLength{2, 0, 1, true}},
{[]byte{0x02, 0x00}, true, tagAndLength{0, 2, 0, false}},
{[]byte{0xfe, 0x00}, true, tagAndLength{3, 30, 0, true}},
- {[]byte{0x1f, 0x01, 0x00}, true, tagAndLength{0, 1, 0, false}},
+ {[]byte{0x1f, 0x1f, 0x00}, true, tagAndLength{0, 31, 0, false}},
{[]byte{0x1f, 0x81, 0x00, 0x00}, true, tagAndLength{0, 128, 0, false}},
{[]byte{0x1f, 0x81, 0x80, 0x01, 0x00}, true, tagAndLength{0, 0x4001, 0, false}},
{[]byte{0x00, 0x81, 0x80}, true, tagAndLength{0, 0, 128, false}},
@@ -382,6 +382,8 @@ var tagAndLengthData = []tagAndLengthTest{
{[]byte{0xa0, 0x81, 0x7f}, false, tagAndLength{}},
// Tag numbers which would overflow int32 are rejected. (The value below is 2^31.)
{[]byte{0x1f, 0x88, 0x80, 0x80, 0x80, 0x00, 0x00}, false, tagAndLength{}},
+ // Long tag number form may not be used for tags that fit in short form.
+ {[]byte{0x1f, 0x1e, 0x00}, false, tagAndLength{}},
}
func TestParseTagAndLength(t *testing.T) {
diff --git a/libgo/go/encoding/asn1/marshal.go b/libgo/go/encoding/asn1/marshal.go
index 6e85858..30797ef 100644
--- a/libgo/go/encoding/asn1/marshal.go
+++ b/libgo/go/encoding/asn1/marshal.go
@@ -17,7 +17,7 @@ import (
// A forkableWriter is an in-memory buffer that can be
// 'forked' to create new forkableWriters that bracket the
-// original. After
+// original. After
// pre, post := w.fork()
// the overall sequence of bytes represented is logically w+pre+post.
type forkableWriter struct {
@@ -315,9 +315,9 @@ func marshalUTCTime(out *forkableWriter, t time.Time) (err error) {
switch {
case 1950 <= year && year < 2000:
- err = marshalTwoDigits(out, int(year-1900))
+ err = marshalTwoDigits(out, year-1900)
case 2000 <= year && year < 2050:
- err = marshalTwoDigits(out, int(year-2000))
+ err = marshalTwoDigits(out, year-2000)
default:
return StructuralError{"cannot represent time as UTCTime"}
}
@@ -435,7 +435,7 @@ func marshalBody(out *forkableWriter, value reflect.Value, params fieldParameter
return out.WriteByte(0)
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return marshalInt64(out, int64(v.Int()))
+ return marshalInt64(out, v.Int())
case reflect.Struct:
t := v.Type()
diff --git a/libgo/go/encoding/base32/base32.go b/libgo/go/encoding/base32/base32.go
index 5a9e869..c193e65 100644
--- a/libgo/go/encoding/base32/base32.go
+++ b/libgo/go/encoding/base32/base32.go
@@ -17,7 +17,7 @@ import (
*/
// An Encoding is a radix 32 encoding/decoding scheme, defined by a
-// 32-character alphabet. The most common is the "base32" encoding
+// 32-character alphabet. The most common is the "base32" encoding
// introduced for SASL GSSAPI and standardized in RFC 4648.
// The alternate "base32hex" encoding is used in DNSSEC.
type Encoding struct {
@@ -66,7 +66,7 @@ var removeNewlinesMapper = func(r rune) rune {
//
// The encoding pads the output to a multiple of 8 bytes,
// so Encode is not appropriate for use on individual blocks
-// of a large data stream. Use NewEncoder() instead.
+// of a large data stream. Use NewEncoder() instead.
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) == 0 {
return
@@ -208,7 +208,7 @@ func (e *encoder) Close() error {
return e.err
}
-// NewEncoder returns a new base32 stream encoder. Data written to
+// NewEncoder returns a new base32 stream encoder. Data written to
// the returned writer will be encoded using enc and then written to w.
// Base32 encodings operate in 5-byte blocks; when finished
// writing, the caller must Close the returned encoder to flush any
@@ -313,9 +313,9 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
return n, end, nil
}
-// Decode decodes src using the encoding enc. It writes at most
+// Decode decodes src using the encoding enc. It writes at most
// DecodedLen(len(src)) bytes to dst and returns the number of bytes
-// written. If src contains invalid base32 data, it will return the
+// written. If src contains invalid base32 data, it will return the
// number of bytes successfully written and CorruptInputError.
// New line characters (\r and \n) are ignored.
func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
diff --git a/libgo/go/encoding/base32/base32_test.go b/libgo/go/encoding/base32/base32_test.go
index 5a68f06..66a48a3 100644
--- a/libgo/go/encoding/base32/base32_test.go
+++ b/libgo/go/encoding/base32/base32_test.go
@@ -171,7 +171,7 @@ func TestDecodeCorrupt(t *testing.T) {
_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
if tc.offset == -1 {
if err != nil {
- t.Error("Decoder wrongly detected coruption in", tc.input)
+ t.Error("Decoder wrongly detected corruption in", tc.input)
}
continue
}
diff --git a/libgo/go/encoding/base64/base64.go b/libgo/go/encoding/base64/base64.go
index 1bda804..c2116d8 100644
--- a/libgo/go/encoding/base64/base64.go
+++ b/libgo/go/encoding/base64/base64.go
@@ -15,7 +15,7 @@ import (
*/
// An Encoding is a radix 64 encoding/decoding scheme, defined by a
-// 64-character alphabet. The most common encoding is the "base64"
+// 64-character alphabet. The most common encoding is the "base64"
// encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
// (RFC 1421). RFC 4648 also defines an alternate encoding, which is
// the standard encoding with - and _ substituted for + and /.
@@ -89,7 +89,7 @@ var RawURLEncoding = URLEncoding.WithPadding(NoPadding)
//
// The encoding pads the output to a multiple of 4 bytes,
// so Encode is not appropriate for use on individual blocks
-// of a large data stream. Use NewEncoder() instead.
+// of a large data stream. Use NewEncoder() instead.
func (enc *Encoding) Encode(dst, src []byte) {
if len(src) == 0 {
return
@@ -213,7 +213,7 @@ func (e *encoder) Close() error {
return e.err
}
-// NewEncoder returns a new base64 stream encoder. Data written to
+// NewEncoder returns a new base64 stream encoder. Data written to
// the returned writer will be encoded using enc and then written to w.
// Base64 encodings operate in 4-byte blocks; when finished
// writing, the caller must Close the returned encoder to flush any
@@ -328,9 +328,9 @@ func (enc *Encoding) decode(dst, src []byte) (n int, end bool, err error) {
return n, end, err
}
-// Decode decodes src using the encoding enc. It writes at most
+// Decode decodes src using the encoding enc. It writes at most
// DecodedLen(len(src)) bytes to dst and returns the number of bytes
-// written. If src contains invalid base64 data, it will return the
+// written. If src contains invalid base64 data, it will return the
// number of bytes successfully written and CorruptInputError.
// New line characters (\r and \n) are ignored.
func (enc *Encoding) Decode(dst, src []byte) (n int, err error) {
@@ -459,7 +459,7 @@ func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
func (enc *Encoding) DecodedLen(n int) int {
if enc.padChar == NoPadding {
// Unpadded data may end with partial block of 2-3 characters.
- return (n*6 + 7) / 8
+ return n * 6 / 8
}
// Padded base64 should always be a multiple of 4 characters in length.
return n / 4 * 3
diff --git a/libgo/go/encoding/base64/base64_test.go b/libgo/go/encoding/base64/base64_test.go
index fc6a1ea..19ddb92 100644
--- a/libgo/go/encoding/base64/base64_test.go
+++ b/libgo/go/encoding/base64/base64_test.go
@@ -221,7 +221,7 @@ func TestDecodeCorrupt(t *testing.T) {
_, err := StdEncoding.Decode(dbuf, []byte(tc.input))
if tc.offset == -1 {
if err != nil {
- t.Error("Decoder wrongly detected coruption in", tc.input)
+ t.Error("Decoder wrongly detected corruption in", tc.input)
}
continue
}
@@ -234,6 +234,51 @@ func TestDecodeCorrupt(t *testing.T) {
}
}
+func TestEncodedLen(t *testing.T) {
+ for _, tt := range []struct {
+ enc *Encoding
+ n int
+ want int
+ }{
+ {RawStdEncoding, 0, 0},
+ {RawStdEncoding, 1, 2},
+ {RawStdEncoding, 2, 3},
+ {RawStdEncoding, 3, 4},
+ {RawStdEncoding, 7, 10},
+ {StdEncoding, 0, 0},
+ {StdEncoding, 1, 4},
+ {StdEncoding, 2, 4},
+ {StdEncoding, 3, 4},
+ {StdEncoding, 4, 8},
+ {StdEncoding, 7, 12},
+ } {
+ if got := tt.enc.EncodedLen(tt.n); got != tt.want {
+ t.Errorf("EncodedLen(%d): got %d, want %d", tt.n, got, tt.want)
+ }
+ }
+}
+
+func TestDecodedLen(t *testing.T) {
+ for _, tt := range []struct {
+ enc *Encoding
+ n int
+ want int
+ }{
+ {RawStdEncoding, 0, 0},
+ {RawStdEncoding, 2, 1},
+ {RawStdEncoding, 3, 2},
+ {RawStdEncoding, 4, 3},
+ {RawStdEncoding, 10, 7},
+ {StdEncoding, 0, 0},
+ {StdEncoding, 4, 3},
+ {StdEncoding, 8, 6},
+ } {
+ if got := tt.enc.DecodedLen(tt.n); got != tt.want {
+ t.Errorf("DecodedLen(%d): got %d, want %d", tt.n, got, tt.want)
+ }
+ }
+}
+
func TestBig(t *testing.T) {
n := 3*1000 + 1
raw := make([]byte, n)
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go
index 1c2577b..46c6add 100644
--- a/libgo/go/encoding/binary/binary.go
+++ b/libgo/go/encoding/binary/binary.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -48,18 +48,24 @@ var BigEndian bigEndian
type littleEndian struct{}
-func (littleEndian) Uint16(b []byte) uint16 { return uint16(b[0]) | uint16(b[1])<<8 }
+func (littleEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[0]) | uint16(b[1])<<8
+}
func (littleEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
}
func (littleEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func (littleEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
@@ -67,11 +73,13 @@ func (littleEndian) PutUint32(b []byte, v uint32) {
}
func (littleEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
func (littleEndian) PutUint64(b []byte, v uint64) {
+ _ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v)
b[1] = byte(v >> 8)
b[2] = byte(v >> 16)
@@ -88,18 +96,24 @@ func (littleEndian) GoString() string { return "binary.LittleEndian" }
type bigEndian struct{}
-func (bigEndian) Uint16(b []byte) uint16 { return uint16(b[1]) | uint16(b[0])<<8 }
+func (bigEndian) Uint16(b []byte) uint16 {
+ _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808
+ return uint16(b[1]) | uint16(b[0])<<8
+}
func (bigEndian) PutUint16(b []byte, v uint16) {
+ _ = b[1] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 8)
b[1] = byte(v)
}
func (bigEndian) Uint32(b []byte) uint32 {
+ _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}
func (bigEndian) PutUint32(b []byte, v uint32) {
+ _ = b[3] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 24)
b[1] = byte(v >> 16)
b[2] = byte(v >> 8)
@@ -107,11 +121,13 @@ func (bigEndian) PutUint32(b []byte, v uint32) {
}
func (bigEndian) Uint64(b []byte) uint64 {
+ _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
}
func (bigEndian) PutUint64(b []byte, v uint64) {
+ _ = b[7] // early bounds check to guarantee safety of writes below
b[0] = byte(v >> 56)
b[1] = byte(v >> 48)
b[2] = byte(v >> 40)
@@ -253,7 +269,7 @@ func Write(w io.Writer, order ByteOrder, data interface{}) error {
case *uint8:
b[0] = *v
case uint8:
- b[0] = byte(v)
+ b[0] = v
case []uint8:
bs = v
case *int16:
diff --git a/libgo/go/encoding/binary/binary_test.go b/libgo/go/encoding/binary/binary_test.go
index 7fd36fa..c0728e9 100644
--- a/libgo/go/encoding/binary/binary_test.go
+++ b/libgo/go/encoding/binary/binary_test.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -266,7 +266,7 @@ func TestBlankFields(t *testing.T) {
}
// An attempt to read into a struct with an unexported field will
-// panic. This is probably not the best choice, but at this point
+// panic. This is probably not the best choice, but at this point
// anything else would be an API change.
type Unexported struct {
@@ -339,6 +339,33 @@ func TestReadTruncated(t *testing.T) {
}
}
+func testUint64SmallSliceLengthPanics() (panicked bool) {
+ defer func() {
+ panicked = recover() != nil
+ }()
+ b := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
+ LittleEndian.Uint64(b[:4])
+ return false
+}
+
+func testPutUint64SmallSliceLengthPanics() (panicked bool) {
+ defer func() {
+ panicked = recover() != nil
+ }()
+ b := [8]byte{}
+ LittleEndian.PutUint64(b[:4], 0x0102030405060708)
+ return false
+}
+
+func TestEarlyBoundsChecks(t *testing.T) {
+ if testUint64SmallSliceLengthPanics() != true {
+ t.Errorf("binary.LittleEndian.Uint64 expected to panic for small slices, but didn't")
+ }
+ if testPutUint64SmallSliceLengthPanics() != true {
+ t.Errorf("binary.LittleEndian.PutUint64 expected to panic for small slices, but didn't")
+ }
+}
+
type byteSliceReader struct {
remain []byte
}
@@ -373,8 +400,8 @@ func BenchmarkReadStruct(b *testing.B) {
Read(bsr, BigEndian, &t)
}
b.StopTimer()
- if !reflect.DeepEqual(s, t) {
- b.Fatal("no match")
+ if b.N > 0 && !reflect.DeepEqual(s, t) {
+ b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", t, s)
}
}
@@ -405,8 +432,8 @@ func BenchmarkReadInts(b *testing.B) {
want.Array[i] = 0
}
b.StopTimer()
- if !reflect.DeepEqual(ls, want) {
- panic("no match")
+ if b.N > 0 && !reflect.DeepEqual(ls, want) {
+ b.Fatalf("struct doesn't match:\ngot %v;\nwant %v", ls, want)
}
}
@@ -427,7 +454,7 @@ func BenchmarkWriteInts(b *testing.B) {
Write(w, BigEndian, s.Uint64)
}
b.StopTimer()
- if !bytes.Equal(buf.Bytes(), big[:30]) {
+ if b.N > 0 && !bytes.Equal(buf.Bytes(), big[:30]) {
b.Fatalf("first half doesn't match: %x %x", buf.Bytes(), big[:30])
}
}
diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go
index 3a2dfa3c..d7a75f9 100644
--- a/libgo/go/encoding/binary/varint.go
+++ b/libgo/go/encoding/binary/varint.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/csv/reader.go b/libgo/go/encoding/csv/reader.go
index a6bb780..a5e03a9 100644
--- a/libgo/go/encoding/csv/reader.go
+++ b/libgo/go/encoding/csv/reader.go
@@ -3,6 +3,8 @@
// license that can be found in the LICENSE file.
// Package csv reads and writes comma-separated values (CSV) files.
+// There are many kinds of CSV files; this package supports the format
+// described in RFC 4180.
//
// A csv file contains zero or more records of one or more fields per record.
// Each record is separated by the newline character. The final record may
@@ -14,11 +16,11 @@
//
// Carriage returns before newline characters are silently removed.
//
-// Blank lines are ignored. A line with only whitespace characters (excluding
+// Blank lines are ignored. A line with only whitespace characters (excluding
// the ending newline character) is not considered a blank line.
//
// Fields which start and stop with the quote character " are called
-// quoted-fields. The beginning and ending quote are not part of the
+// quoted-fields. The beginning and ending quote are not part of the
// field.
//
// The source:
@@ -84,32 +86,35 @@ var (
// The exported fields can be changed to customize the details before the
// first call to Read or ReadAll.
//
-// Comma is the field delimiter. It defaults to ','.
//
-// Comment, if not 0, is the comment character. Lines beginning with the
-// Comment character are ignored.
-//
-// If FieldsPerRecord is positive, Read requires each record to
-// have the given number of fields. If FieldsPerRecord is 0, Read sets it to
-// the number of fields in the first record, so that future records must
-// have the same field count. If FieldsPerRecord is negative, no check is
-// made and records may have a variable number of fields.
-//
-// If LazyQuotes is true, a quote may appear in an unquoted field and a
-// non-doubled quote may appear in a quoted field.
-//
-// If TrimLeadingSpace is true, leading white space in a field is ignored.
type Reader struct {
- Comma rune // field delimiter (set to ',' by NewReader)
- Comment rune // comment character for start of line
- FieldsPerRecord int // number of expected fields per record
- LazyQuotes bool // allow lazy quotes
- TrailingComma bool // ignored; here for backwards compatibility
- TrimLeadingSpace bool // trim leading space
- line int
- column int
- r *bufio.Reader
- field bytes.Buffer
+ // Comma is the field delimiter.
+ // It is set to comma (',') by NewReader.
+ Comma rune
+ // Comment, if not 0, is the comment character. Lines beginning with the
+ // Comment character without preceding whitespace are ignored.
+ // With leading whitespace the Comment character becomes part of the
+ // field, even if TrimLeadingSpace is true.
+ Comment rune
+ // FieldsPerRecord is the number of expected fields per record.
+ // If FieldsPerRecord is positive, Read requires each record to
+ // have the given number of fields. If FieldsPerRecord is 0, Read sets it to
+ // the number of fields in the first record, so that future records must
+ // have the same field count. If FieldsPerRecord is negative, no check is
+ // made and records may have a variable number of fields.
+ FieldsPerRecord int
+ // If LazyQuotes is true, a quote may appear in an unquoted field and a
+ // non-doubled quote may appear in a quoted field.
+ LazyQuotes bool
+ TrailingComma bool // ignored; here for backwards compatibility
+ // If TrimLeadingSpace is true, leading white space in a field is ignored.
+ // This is done even if the field delimiter, Comma, is white space.
+ TrimLeadingSpace bool
+
+ line int
+ column int
+ r *bufio.Reader
+ field bytes.Buffer
}
// NewReader returns a new Reader that reads from r.
@@ -129,7 +134,7 @@ func (r *Reader) error(err error) error {
}
}
-// Read reads one record from r. The record is a slice of strings with each
+// Read reads one record from r. The record is a slice of strings with each
// string representing one field.
func (r *Reader) Read() (record []string, err error) {
for {
@@ -177,7 +182,7 @@ func (r *Reader) ReadAll() (records [][]string, err error) {
func (r *Reader) readRune() (rune, error) {
r1, _, err := r.r.ReadRune()
- // Handle \r\n here. We make the simplifying assumption that
+ // Handle \r\n here. We make the simplifying assumption that
// anytime \r is followed by \n that it can be folded to \n.
// We will not detect files which contain both \r\n and bare \n.
if r1 == '\r' {
@@ -208,13 +213,13 @@ func (r *Reader) skip(delim rune) error {
// parseRecord reads and parses a single csv record from r.
func (r *Reader) parseRecord() (fields []string, err error) {
- // Each record starts on a new line. We increment our line
+ // Each record starts on a new line. We increment our line
// number (lines start at 1, not 0) and set column to -1
// so as we increment in readRune it points to the character we read.
r.line++
r.column = -1
- // Peek at the first rune. If it is an error we are done.
+ // Peek at the first rune. If it is an error we are done.
// If we support comments and it is the comment character
// then skip to the end of line.
@@ -232,7 +237,7 @@ func (r *Reader) parseRecord() (fields []string, err error) {
for {
haveField, delim, err := r.parseField()
if haveField {
- // If FieldsPerRecord is greater then 0 we can assume the final
+ // If FieldsPerRecord is greater than 0 we can assume the final
// length of fields to be equal to FieldsPerRecord.
if r.FieldsPerRecord > 0 && fields == nil {
fields = make([]string, 0, r.FieldsPerRecord)
@@ -247,8 +252,8 @@ func (r *Reader) parseRecord() (fields []string, err error) {
}
}
-// parseField parses the next field in the record. The read field is
-// located in r.field. Delim is the first character not part of the field
+// parseField parses the next field in the record. The read field is
+// located in r.field. Delim is the first character not part of the field
// (r.Comma or '\n').
func (r *Reader) parseField() (haveField bool, delim rune, err error) {
r.field.Reset()
diff --git a/libgo/go/encoding/csv/writer.go b/libgo/go/encoding/csv/writer.go
index 353d91f..84b7aa1 100644
--- a/libgo/go/encoding/csv/writer.go
+++ b/libgo/go/encoding/csv/writer.go
@@ -15,7 +15,7 @@ import (
// A Writer writes records to a CSV encoded file.
//
// As returned by NewWriter, a Writer writes records terminated by a
-// newline and uses ',' as the field delimiter. The exported fields can be
+// newline and uses ',' as the field delimiter. The exported fields can be
// changed to customize the details before the first call to Write or WriteAll.
//
// Comma is the field delimiter.
@@ -37,27 +37,28 @@ func NewWriter(w io.Writer) *Writer {
// Writer writes a single CSV record to w along with any necessary quoting.
// A record is a slice of strings with each string being one field.
-func (w *Writer) Write(record []string) (err error) {
+func (w *Writer) Write(record []string) error {
for n, field := range record {
if n > 0 {
- if _, err = w.w.WriteRune(w.Comma); err != nil {
- return
+ if _, err := w.w.WriteRune(w.Comma); err != nil {
+ return err
}
}
// If we don't have to have a quoted field then just
// write out the field and continue to the next field.
if !w.fieldNeedsQuotes(field) {
- if _, err = w.w.WriteString(field); err != nil {
- return
+ if _, err := w.w.WriteString(field); err != nil {
+ return err
}
continue
}
- if err = w.w.WriteByte('"'); err != nil {
- return
+ if err := w.w.WriteByte('"'); err != nil {
+ return err
}
for _, r1 := range field {
+ var err error
switch r1 {
case '"':
_, err = w.w.WriteString(`""`)
@@ -75,20 +76,21 @@ func (w *Writer) Write(record []string) (err error) {
_, err = w.w.WriteRune(r1)
}
if err != nil {
- return
+ return err
}
}
- if err = w.w.WriteByte('"'); err != nil {
- return
+ if err := w.w.WriteByte('"'); err != nil {
+ return err
}
}
+ var err error
if w.UseCRLF {
_, err = w.w.WriteString("\r\n")
} else {
err = w.w.WriteByte('\n')
}
- return
+ return err
}
// Flush writes any buffered data to the underlying io.Writer.
@@ -104,9 +106,9 @@ func (w *Writer) Error() error {
}
// WriteAll writes multiple CSV records to w using Write and then calls Flush.
-func (w *Writer) WriteAll(records [][]string) (err error) {
+func (w *Writer) WriteAll(records [][]string) error {
for _, record := range records {
- err = w.Write(record)
+ err := w.Write(record)
if err != nil {
return err
}
@@ -130,7 +132,7 @@ func (w *Writer) fieldNeedsQuotes(field string) bool {
if field == "" {
return false
}
- if field == `\.` || strings.IndexRune(field, w.Comma) >= 0 || strings.IndexAny(field, "\"\r\n") >= 0 {
+ if field == `\.` || strings.ContainsRune(field, w.Comma) || strings.ContainsAny(field, "\"\r\n") {
return true
}
diff --git a/libgo/go/encoding/encoding.go b/libgo/go/encoding/encoding.go
index 6d218071..cc5a536 100644
--- a/libgo/go/encoding/encoding.go
+++ b/libgo/go/encoding/encoding.go
@@ -1,4 +1,4 @@
-// Copyright 2013 The Go Authors. All rights reserved.
+// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/gob/codec_test.go b/libgo/go/encoding/gob/codec_test.go
index 8efcdc7..d4002cb 100644
--- a/libgo/go/encoding/gob/codec_test.go
+++ b/libgo/go/encoding/gob/codec_test.go
@@ -970,7 +970,7 @@ func TestBadRecursiveType(t *testing.T) {
err := NewEncoder(b).Encode(&rec)
if err == nil {
t.Error("expected error; got none")
- } else if strings.Index(err.Error(), "recursive") < 0 {
+ } else if !strings.Contains(err.Error(), "recursive") {
t.Error("expected recursive type error; got", err)
}
// Can't test decode easily because we can't encode one, so we can't pass one to a Decoder.
@@ -1253,7 +1253,7 @@ func TestIgnoreInterface(t *testing.T) {
if item2.I != item1.I {
t.Error("normal int did not decode correctly")
}
- if item2.F != item2.F {
+ if item2.F != item1.F {
t.Error("normal float did not decode correctly")
}
}
@@ -1280,7 +1280,7 @@ func TestUnexportedFields(t *testing.T) {
if err != nil {
t.Fatal("decode error:", err)
}
- if u0.A != u0.A || u0.B != u1.B || u0.D != u1.D {
+ if u0.A != u1.A || u0.B != u1.B || u0.D != u1.D {
t.Errorf("u1->u0: expected %v; got %v", u0, u1)
}
if u1.c != 1234. {
diff --git a/libgo/go/encoding/gob/debug.go b/libgo/go/encoding/gob/debug.go
index 536bbdb..d69d36f 100644
--- a/libgo/go/encoding/gob/debug.go
+++ b/libgo/go/encoding/gob/debug.go
@@ -7,7 +7,7 @@
package gob
-// This file is not normally included in the gob package. Used only for debugging the package itself.
+// This file is not normally included in the gob package. Used only for debugging the package itself.
// Except for reading uints, it is an implementation of a reader that is independent of
// the one implemented by Decoder.
// To enable the Debug function, delete the +build ignore line above and do
@@ -241,7 +241,7 @@ func (deb *debugger) delimitedMessage(indent tab) bool {
// loadBlock preps us to read a message
// of the length specified next in the input. It returns
// the length of the block. The argument tells whether
-// an EOF is acceptable now. If it is and one is found,
+// an EOF is acceptable now. If it is and one is found,
// the return value is negative.
func (deb *debugger) loadBlock(eofOK bool) int {
n64, w, err := decodeUintReader(deb.r, deb.tmp) // deb.uint64 will error at EOF
@@ -339,7 +339,7 @@ func (deb *debugger) string() string {
return string(b)
}
-// delta returns the field delta at the input point. The expect argument,
+// delta returns the field delta at the input point. The expect argument,
// if non-negative, identifies what the value should be.
func (deb *debugger) delta(expect int) int {
delta := int(deb.uint64())
diff --git a/libgo/go/encoding/gob/decode.go b/libgo/go/encoding/gob/decode.go
index 3b0dca8..9645dc5 100644
--- a/libgo/go/encoding/gob/decode.go
+++ b/libgo/go/encoding/gob/decode.go
@@ -216,10 +216,10 @@ func ignoreTwoUints(i *decInstr, state *decoderState, v reflect.Value) {
}
// Since the encoder writes no zeros, if we arrive at a decoder we have
-// a value to extract and store. The field number has already been read
+// a value to extract and store. The field number has already been read
// (it's how we knew to call this decoder).
// Each decoder is responsible for handling any indirections associated
-// with the data structure. If any pointer so reached is nil, allocation must
+// with the data structure. If any pointer so reached is nil, allocation must
// be done.
// decAlloc takes a value and returns a settable value that can
@@ -308,9 +308,9 @@ func decUint64(i *decInstr, state *decoderState, value reflect.Value) {
}
// Floating-point numbers are transmitted as uint64s holding the bits
-// of the underlying representation. They are sent byte-reversed, with
+// of the underlying representation. They are sent byte-reversed, with
// the exponent end coming out first, so integer floating point numbers
-// (for example) transmit more compactly. This routine does the
+// (for example) transmit more compactly. This routine does the
// unswizzling.
func float64FromBits(u uint64) float64 {
var v uint64
@@ -332,7 +332,7 @@ func float32FromBits(u uint64, ovfl error) float64 {
if av < 0 {
av = -av
}
- // +Inf is OK in both 32- and 64-bit floats. Underflow is always OK.
+ // +Inf is OK in both 32- and 64-bit floats. Underflow is always OK.
if math.MaxFloat32 < av && av <= math.MaxFloat64 {
error_(ovfl)
}
@@ -421,7 +421,7 @@ func ignoreUint8Array(i *decInstr, state *decoderState, value reflect.Value) {
// Execution engine
// The encoder engine is an array of instructions indexed by field number of the incoming
-// decoder. It is executed with random access according to field number.
+// decoder. It is executed with random access according to field number.
type decEngine struct {
instr []decInstr
numInstr int // the number of active instructions
@@ -442,7 +442,7 @@ func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, value refl
}
// decodeStruct decodes a top-level struct and stores it in value.
-// Indir is for the value, not the type. At the time of the call it may
+// Indir is for the value, not the type. At the time of the call it may
// differ from ut.indir, which was computed when the engine was built.
// This state cannot arise for decodeSingle, which is called directly
// from the user's value, not from the innards of an engine.
@@ -536,7 +536,7 @@ func (dec *Decoder) decodeArrayHelper(state *decoderState, value reflect.Value,
}
// decodeArray decodes an array and stores it in value.
-// The length is an unsigned integer preceding the elements. Even though the length is redundant
+// The length is an unsigned integer preceding the elements. Even though the length is redundant
// (it's part of the type), it's a useful check and is included in the encoding.
func (dec *Decoder) decodeArray(atyp reflect.Type, state *decoderState, value reflect.Value, elemOp decOp, length int, ovfl error, helper decHelper) {
if n := state.decodeUint(); n != uint64(length) {
@@ -645,10 +645,10 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, valu
errorf("invalid type name length %d: exceeds input size", nr)
}
n := int(nr)
- name := string(state.b.Bytes()[:n])
+ name := state.b.Bytes()[:n]
state.b.Drop(n)
// Allocate the destination interface value.
- if name == "" {
+ if len(name) == 0 {
// Copy the nil interface value to the target.
value.Set(reflect.Zero(value.Type()))
return
@@ -658,7 +658,7 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, valu
}
// The concrete type must be registered.
registerLock.RLock()
- typ, ok := nameToConcreteType[name]
+ typ, ok := nameToConcreteType[string(name)]
registerLock.RUnlock()
if !ok {
errorf("name not registered for interface: %q", name)
@@ -1075,7 +1075,7 @@ func (dec *Decoder) compileIgnoreSingle(remoteId typeId) (engine *decEngine, err
return
}
-// compileDec compiles the decoder engine for a value. If the value is not a struct,
+// compileDec compiles the decoder engine for a value. If the value is not a struct,
// it calls out to compileSingle.
func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err error) {
defer catchError(&err)
diff --git a/libgo/go/encoding/gob/decoder.go b/libgo/go/encoding/gob/decoder.go
index c453e9b..c182941 100644
--- a/libgo/go/encoding/gob/decoder.go
+++ b/libgo/go/encoding/gob/decoder.go
@@ -130,9 +130,9 @@ func (dec *Decoder) nextUint() uint64 {
// decodeTypeSequence parses:
// TypeSequence
// (TypeDefinition DelimitedTypeDefinition*)?
-// and returns the type id of the next value. It returns -1 at
+// and returns the type id of the next value. It returns -1 at
// EOF. Upon return, the remainder of dec.buf is the value to be
-// decoded. If this is an interface value, it can be ignored by
+// decoded. If this is an interface value, it can be ignored by
// resetting that buffer.
func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
for dec.err == nil {
@@ -150,7 +150,7 @@ func (dec *Decoder) decodeTypeSequence(isInterface bool) typeId {
// Type definition for (-id) follows.
dec.recvType(-id)
// When decoding an interface, after a type there may be a
- // DelimitedValue still in the buffer. Skip its count.
+ // DelimitedValue still in the buffer. Skip its count.
// (Alternatively, the buffer is empty and the byte count
// will be absorbed by recvMessage.)
if dec.buf.Len() > 0 {
@@ -177,7 +177,7 @@ func (dec *Decoder) Decode(e interface{}) error {
}
value := reflect.ValueOf(e)
// If e represents a value as opposed to a pointer, the answer won't
- // get back to the caller. Make sure it's a pointer.
+ // get back to the caller. Make sure it's a pointer.
if value.Type().Kind() != reflect.Ptr {
dec.err = errors.New("gob: attempt to decode into a non-pointer")
return dec.err
@@ -187,7 +187,7 @@ func (dec *Decoder) Decode(e interface{}) error {
// DecodeValue reads the next value from the input stream.
// If v is the zero reflect.Value (v.Kind() == Invalid), DecodeValue discards the value.
-// Otherwise, it stores the value into v. In that case, v must represent
+// Otherwise, it stores the value into v. In that case, v must represent
// a non-nil pointer to data or be an assignable reflect.Value (v.CanSet())
// If the input is at EOF, DecodeValue returns io.EOF and
// does not modify v.
diff --git a/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go
index cf878f4..1536574 100644
--- a/libgo/go/encoding/gob/doc.go
+++ b/libgo/go/encoding/gob/doc.go
@@ -17,7 +17,8 @@ Basics
A stream of gobs is self-describing. Each data item in the stream is preceded by
a specification of its type, expressed in terms of a small set of predefined
types. Pointers are not transmitted, but the things they point to are
-transmitted; that is, the values are flattened. Recursive types work fine, but
+transmitted; that is, the values are flattened. Nil pointers are not permitted,
+as they have no value. Recursive types work fine, but
recursive values (data with cycles) are problematic. This may change.
To use gobs, create an Encoder and present it with a series of data items as
@@ -254,6 +255,12 @@ In summary, a gob stream looks like
where * signifies zero or more repetitions and the type id of a value must
be predefined or be defined before the value in the stream.
+Compatibility: Any future changes to the package will endeavor to maintain
+compatibility with streams encoded using previous versions. That is, any released
+version of this package should be able to decode data written with any previously
+released version, subject to issues such as security fixes. See the Go compatibility
+document for background: https://golang.org/doc/go1compat
+
See "Gobs of data" for a design discussion of the gob wire format:
https://blog.golang.org/gobs-of-data
*/
diff --git a/libgo/go/encoding/gob/encode.go b/libgo/go/encoding/gob/encode.go
index 96052ef..50cd6ad 100644
--- a/libgo/go/encoding/gob/encode.go
+++ b/libgo/go/encoding/gob/encode.go
@@ -96,7 +96,7 @@ func (enc *Encoder) freeEncoderState(e *encoderState) {
enc.freeList = e
}
-// Unsigned integers have a two-state encoding. If the number is less
+// Unsigned integers have a two-state encoding. If the number is less
// than 128 (0 through 0x7F), its value is written directly.
// Otherwise the value is written in big-endian byte order preceded
// by the byte length, negated.
@@ -127,7 +127,7 @@ func (state *encoderState) encodeInt(i int64) {
} else {
x = uint64(i << 1)
}
- state.encodeUint(uint64(x))
+ state.encodeUint(x)
}
// encOp is the signature of an encoding operator for a given type.
@@ -152,8 +152,8 @@ func (state *encoderState) update(instr *encInstr) {
// Each encoder for a composite is responsible for handling any
// indirections associated with the elements of the data structure.
-// If any pointer so reached is nil, no bytes are written. If the
-// data item is zero, no bytes are written. Single values - ints,
+// If any pointer so reached is nil, no bytes are written. If the
+// data item is zero, no bytes are written. Single values - ints,
// strings etc. - are indirected before calling their encoders.
// Otherwise, the output (for a scalar) is the field number, as an
// encoded integer, followed by the field data in its appropriate
@@ -203,9 +203,9 @@ func encUint(i *encInstr, state *encoderState, v reflect.Value) {
// floatBits returns a uint64 holding the bits of a floating-point number.
// Floating-point numbers are transmitted as uint64s holding the bits
-// of the underlying representation. They are sent byte-reversed, with
+// of the underlying representation. They are sent byte-reversed, with
// the exponent end coming out first, so integer floating point numbers
-// (for example) transmit more compactly. This routine does the
+// (for example) transmit more compactly. This routine does the
// swizzling.
func floatBits(f float64) uint64 {
u := math.Float64bits(f)
@@ -272,7 +272,7 @@ func encStructTerminator(i *encInstr, state *encoderState, v reflect.Value) {
// Execution engine
// encEngine an array of instructions indexed by field number of the encoding
-// data, typically a struct. It is executed top to bottom, walking the struct.
+// data, typically a struct. It is executed top to bottom, walking the struct.
type encEngine struct {
instr []encInstr
}
@@ -297,7 +297,7 @@ func (enc *Encoder) encodeSingle(b *encBuffer, engine *encEngine, value reflect.
defer enc.freeEncoderState(state)
state.fieldnum = singletonField
// There is no surrounding struct to frame the transmission, so we must
- // generate data even if the item is zero. To do this, set sendZero.
+ // generate data even if the item is zero. To do this, set sendZero.
state.sendZero = true
instr := &engine.instr[singletonField]
if instr.indir > 0 {
@@ -386,7 +386,7 @@ func (enc *Encoder) encodeMap(b *encBuffer, mv reflect.Value, keyOp, elemOp encO
// encodeInterface encodes the interface value iv.
// To send an interface, we send a string identifying the concrete type, followed
// by the type identifier (which might require defining that type right now), followed
-// by the concrete value. A nil value gets sent as the empty string for the name,
+// by the concrete value. A nil value gets sent as the empty string for the name,
// followed by no value.
func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) {
// Gobs can encode nil interface values but not typed interface
@@ -417,7 +417,7 @@ func (enc *Encoder) encodeInterface(b *encBuffer, iv reflect.Value) {
enc.sendTypeDescriptor(enc.writer(), state, ut)
// Send the type id.
enc.sendTypeId(state, ut)
- // Encode the value into a new buffer. Any nested type definitions
+ // Encode the value into a new buffer. Any nested type definitions
// should be written to b, before the encoded value.
enc.pushWriter(b)
data := encBufferPool.Get().(*encBuffer)
diff --git a/libgo/go/encoding/gob/encoder.go b/libgo/go/encoding/gob/encoder.go
index 62d0f42..d6c8fdd 100644
--- a/libgo/go/encoding/gob/encoder.go
+++ b/libgo/go/encoding/gob/encoder.go
@@ -170,6 +170,7 @@ func (enc *Encoder) sendType(w io.Writer, state *encoderState, origt reflect.Typ
// Encode transmits the data item represented by the empty interface value,
// guaranteeing that all necessary type information has been transmitted first.
+// Passing a nil pointer to Encoder will panic, as they cannot be transmitted by gob.
func (enc *Encoder) Encode(e interface{}) error {
return enc.EncodeValue(reflect.ValueOf(e))
}
@@ -191,7 +192,7 @@ func (enc *Encoder) sendTypeDescriptor(w io.Writer, state *encoderState, ut *use
return
}
// If the type info has still not been transmitted, it means we have
- // a singleton basic type (int, []byte etc.) at top level. We don't
+ // a singleton basic type (int, []byte etc.) at top level. We don't
// need to send the type info but we do need to update enc.sent.
if !sent {
info, err := getTypeInfo(ut)
@@ -212,9 +213,8 @@ func (enc *Encoder) sendTypeId(state *encoderState, ut *userTypeInfo) {
// EncodeValue transmits the data item represented by the reflection value,
// guaranteeing that all necessary type information has been transmitted first.
+// Passing a nil pointer to EncodeValue will panic, as they cannot be transmitted by gob.
func (enc *Encoder) EncodeValue(value reflect.Value) error {
- // Gobs contain values. They cannot represent nil pointers, which
- // have no value to encode.
if value.Kind() == reflect.Ptr && value.IsNil() {
panic("gob: cannot encode nil pointer of type " + value.Type().String())
}
diff --git a/libgo/go/encoding/gob/encoder_test.go b/libgo/go/encoding/gob/encoder_test.go
index 570d796..22090a1 100644
--- a/libgo/go/encoding/gob/encoder_test.go
+++ b/libgo/go/encoding/gob/encoder_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"encoding/hex"
"fmt"
+ "io/ioutil"
"reflect"
"strings"
"testing"
@@ -280,7 +281,7 @@ func TestValueError(t *testing.T) {
}
t4p := &Type4{3}
var t4 Type4 // note: not a pointer.
- if err := encAndDec(t4p, t4); err == nil || strings.Index(err.Error(), "pointer") < 0 {
+ if err := encAndDec(t4p, t4); err == nil || !strings.Contains(err.Error(), "pointer") {
t.Error("expected error about pointer; got", err)
}
}
@@ -388,7 +389,7 @@ func TestSingletons(t *testing.T) {
t.Errorf("expected error decoding %v: %s", test.in, test.err)
continue
case err != nil && test.err != "":
- if strings.Index(err.Error(), test.err) < 0 {
+ if !strings.Contains(err.Error(), test.err) {
t.Errorf("wrong error decoding %v: wanted %s, got %v", test.in, test.err, err)
}
continue
@@ -414,7 +415,7 @@ func TestStructNonStruct(t *testing.T) {
var ns NonStruct
if err := encAndDec(s, &ns); err == nil {
t.Error("should get error for struct/non-struct")
- } else if strings.Index(err.Error(), "type") < 0 {
+ } else if !strings.Contains(err.Error(), "type") {
t.Error("for struct/non-struct expected type error; got", err)
}
// Now try the other way
@@ -424,7 +425,7 @@ func TestStructNonStruct(t *testing.T) {
}
if err := encAndDec(ns, &s); err == nil {
t.Error("should get error for non-struct/struct")
- } else if strings.Index(err.Error(), "type") < 0 {
+ } else if !strings.Contains(err.Error(), "type") {
t.Error("for non-struct/struct expected type error; got", err)
}
}
@@ -439,8 +440,8 @@ func (this *interfaceIndirectTestT) F() bool {
return true
}
-// A version of a bug reported on golang-nuts. Also tests top-level
-// slice of interfaces. The issue was registering *T caused T to be
+// A version of a bug reported on golang-nuts. Also tests top-level
+// slice of interfaces. The issue was registering *T caused T to be
// stored as the concrete type.
func TestInterfaceIndirect(t *testing.T) {
Register(&interfaceIndirectTestT{})
@@ -463,7 +464,7 @@ func TestInterfaceIndirect(t *testing.T) {
// Also, when the ignored object contains an interface value, it may define
// types. Make sure that skipping the value still defines the types by using
-// the encoder/decoder pair to send a value afterwards. If an interface
+// the encoder/decoder pair to send a value afterwards. If an interface
// is sent, its type in the test is always NewType0, so this checks that the
// encoder and decoder don't skew with respect to type definitions.
@@ -603,10 +604,6 @@ type Bug1Elem struct {
type Bug1StructMap map[string]Bug1Elem
-func bug1EncDec(in Bug1StructMap, out *Bug1StructMap) error {
- return nil
-}
-
func TestMapBug1(t *testing.T) {
in := make(Bug1StructMap)
in["val1"] = Bug1Elem{"elem1", 1}
@@ -835,30 +832,81 @@ func TestPtrToMapOfMap(t *testing.T) {
// A top-level nil pointer generates a panic with a helpful string-valued message.
func TestTopLevelNilPointer(t *testing.T) {
- errMsg := topLevelNilPanic(t)
- if errMsg == "" {
+ var ip *int
+ encodeErr, panicErr := encodeAndRecover(ip)
+ if encodeErr != nil {
+ t.Fatal("error in encode:", encodeErr)
+ }
+ if panicErr == nil {
t.Fatal("top-level nil pointer did not panic")
}
+ errMsg := panicErr.Error()
if !strings.Contains(errMsg, "nil pointer") {
t.Fatal("expected nil pointer error, got:", errMsg)
}
}
-func topLevelNilPanic(t *testing.T) (panicErr string) {
+func encodeAndRecover(value interface{}) (encodeErr, panicErr error) {
defer func() {
e := recover()
- if err, ok := e.(string); ok {
- panicErr = err
+ if e != nil {
+ switch err := e.(type) {
+ case error:
+ panicErr = err
+ default:
+ panicErr = fmt.Errorf("%v", err)
+ }
}
}()
- var ip *int
- buf := new(bytes.Buffer)
- if err := NewEncoder(buf).Encode(ip); err != nil {
- t.Fatal("error in encode:", err)
- }
+
+ encodeErr = NewEncoder(ioutil.Discard).Encode(value)
return
}
+func TestNilPointerPanics(t *testing.T) {
+ var (
+ nilStringPtr *string
+ intMap = make(map[int]int)
+ intMapPtr = &intMap
+ nilIntMapPtr *map[int]int
+ zero int
+ nilBoolChannel chan bool
+ nilBoolChannelPtr *chan bool
+ nilStringSlice []string
+ stringSlice = make([]string, 1)
+ nilStringSlicePtr *[]string
+ )
+
+ testCases := []struct {
+ value interface{}
+ mustPanic bool
+ }{
+ {nilStringPtr, true},
+ {intMap, false},
+ {intMapPtr, false},
+ {nilIntMapPtr, true},
+ {zero, false},
+ {nilStringSlice, false},
+ {stringSlice, false},
+ {nilStringSlicePtr, true},
+ {nilBoolChannel, false},
+ {nilBoolChannelPtr, true},
+ }
+
+ for _, tt := range testCases {
+ _, panicErr := encodeAndRecover(tt.value)
+ if tt.mustPanic {
+ if panicErr == nil {
+ t.Errorf("expected panic with input %#v, did not panic", tt.value)
+ }
+ continue
+ }
+ if panicErr != nil {
+ t.Fatalf("expected no panic with input %#v, got panic=%v", tt.value, panicErr)
+ }
+ }
+}
+
func TestNilPointerInsideInterface(t *testing.T) {
var ip *int
si := struct {
@@ -913,7 +961,7 @@ func TestMutipleEncodingsOfBadType(t *testing.T) {
// There was an error check comparing the length of the input with the
// length of the slice being decoded. It was wrong because the next
// thing in the input might be a type definition, which would lead to
-// an incorrect length check. This test reproduces the corner case.
+// an incorrect length check. This test reproduces the corner case.
type Z struct {
}
diff --git a/libgo/go/encoding/gob/error.go b/libgo/go/encoding/gob/error.go
index 92cc0c6..8b5265c 100644
--- a/libgo/go/encoding/gob/error.go
+++ b/libgo/go/encoding/gob/error.go
@@ -9,7 +9,7 @@ import "fmt"
// Errors in decoding and encoding are handled using panic and recover.
// Panics caused by user error (that is, everything except run-time panics
// such as "index out of bounds" errors) do not leave the file that caused
-// them, but are instead turned into plain error returns. Encoding and
+// them, but are instead turned into plain error returns. Encoding and
// decoding functions and methods that do not return an error either use
// panic to report an error or are guaranteed error-free.
@@ -30,7 +30,7 @@ func error_(err error) {
}
// catchError is meant to be used as a deferred function to turn a panic(gobError) into a
-// plain error. It overwrites the error return of the function that deferred its call.
+// plain error. It overwrites the error return of the function that deferred its call.
func catchError(err *error) {
if e := recover(); e != nil {
ge, ok := e.(gobError)
diff --git a/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go
index eb76b48..ecc91ee 100644
--- a/libgo/go/encoding/gob/gobencdec_test.go
+++ b/libgo/go/encoding/gob/gobencdec_test.go
@@ -376,7 +376,7 @@ func TestGobEncoderIndirectArrayField(t *testing.T) {
}
// As long as the fields have the same name and implement the
-// interface, we can cross-connect them. Not sure it's useful
+// interface, we can cross-connect them. Not sure it's useful
// and may even be bad but it works and it's hard to prevent
// without exposing the contents of the object, which would
// defeat the purpose.
@@ -434,7 +434,7 @@ func TestGobEncoderValueEncoder(t *testing.T) {
}
// Test that we can use a value then a pointer type of a GobEncoder
-// in the same encoded value. Bug 4647.
+// in the same encoded value. Bug 4647.
func TestGobEncoderValueThenPointer(t *testing.T) {
v := ValueGobber("forty-two")
w := ValueGobber("six-by-nine")
@@ -548,7 +548,7 @@ func TestGobEncoderFieldTypeError(t *testing.T) {
if err == nil {
t.Fatal("expected decode error for mismatched fields (encoder to non-decoder)")
}
- if strings.Index(err.Error(), "type") < 0 {
+ if !strings.Contains(err.Error(), "type") {
t.Fatal("expected type error; got", err)
}
// Non-encoder to GobDecoder: error
@@ -562,7 +562,7 @@ func TestGobEncoderFieldTypeError(t *testing.T) {
if err == nil {
t.Fatal("expected decode error for mismatched fields (non-encoder to decoder)")
}
- if strings.Index(err.Error(), "type") < 0 {
+ if !strings.Contains(err.Error(), "type") {
t.Fatal("expected type error; got", err)
}
}
diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go
index cf5cec0..c27f7e9 100644
--- a/libgo/go/encoding/gob/type.go
+++ b/libgo/go/encoding/gob/type.go
@@ -17,7 +17,7 @@ import (
)
// userTypeInfo stores the information associated with a type the user has handed
-// to the package. It's computed once and stored in a map keyed by reflection
+// to the package. It's computed once and stored in a map keyed by reflection
// type.
type userTypeInfo struct {
user reflect.Type // the type the user handed us
@@ -44,7 +44,7 @@ var (
)
// validType returns, and saves, the information associated with user-provided type rt.
-// If the user type is not valid, err will be non-nil. To be used when the error handler
+// If the user type is not valid, err will be non-nil. To be used when the error handler
// is not set up.
func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) {
userTypeLock.RLock()
@@ -64,7 +64,7 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) {
ut.base = rt
ut.user = rt
// A type that is just a cycle of pointers (such as type T *T) cannot
- // be represented in gobs, which need some concrete data. We use a
+ // be represented in gobs, which need some concrete data. We use a
// cycle detection algorithm from Knuth, Vol 2, Section 3.1, Ex 6,
// pp 539-540. As we step through indirections, run another type at
// half speed. If they meet up, there's a cycle.
@@ -493,7 +493,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, err
// For arrays, maps, and slices, we set the type id after the elements
// are constructed. This is to retain the order of type id allocation after
// a fix made to handle recursive types, which changed the order in
- // which types are built. Delaying the setting in this way preserves
+ // which types are built. Delaying the setting in this way preserves
// type ids while allowing recursive types to be described. Structs,
// done below, were already handling recursion correctly so they
// assign the top-level id before those of the field.
@@ -597,7 +597,7 @@ func getBaseType(name string, rt reflect.Type) (gobType, error) {
// getType returns the Gob type describing the given reflect.Type.
// Should be called only when handling GobEncoders/Decoders,
-// which may be pointers. All other types are handled through the
+// which may be pointers. All other types are handled through the
// base type, never a pointer.
// typeLock must be held.
func getType(name string, ut *userTypeInfo, rt reflect.Type) (gobType, error) {
@@ -642,7 +642,7 @@ func bootstrapType(name string, e interface{}, expect typeId) typeId {
// For bootstrapping purposes, we assume that the recipient knows how
// to decode a wireType; it is exactly the wireType struct here, interpreted
// using the gob rules for sending a structure, except that we assume the
-// ids for wireType and structType etc. are known. The relevant pieces
+// ids for wireType and structType etc. are known. The relevant pieces
// are built in encode.go's init() function.
// To maintain binary compatibility, if you extend this type, always put
// the new fields last.
@@ -789,7 +789,7 @@ func mustGetTypeInfo(rt reflect.Type) *typeInfo {
//
// Note: Since gobs can be stored permanently, it is good design
// to guarantee the encoding used by a GobEncoder is stable as the
-// software evolves. For instance, it might make sense for GobEncode
+// software evolves. For instance, it might make sense for GobEncode
// to include a version number in the encoding.
type GobEncoder interface {
// GobEncode returns a byte slice representing the encoding of the
@@ -838,8 +838,8 @@ func RegisterName(name string, value interface{}) {
}
// Register records a type, identified by a value for that type, under its
-// internal type name. That name will identify the concrete type of a value
-// sent or received as an interface variable. Only types that will be
+// internal type name. That name will identify the concrete type of a value
+// sent or received as an interface variable. Only types that will be
// transferred as implementations of interface values need to be registered.
// Expecting to be used only during initialization, it panics if the mapping
// between types and names is not a bijection.
diff --git a/libgo/go/encoding/hex/hex.go b/libgo/go/encoding/hex/hex.go
index d1fc702..73a2503 100644
--- a/libgo/go/encoding/hex/hex.go
+++ b/libgo/go/encoding/hex/hex.go
@@ -18,7 +18,7 @@ const hextable = "0123456789abcdef"
func EncodedLen(n int) int { return n * 2 }
// Encode encodes src into EncodedLen(len(src))
-// bytes of dst. As a convenience, it returns the number
+// bytes of dst. As a convenience, it returns the number
// of bytes written to dst, but this value is always EncodedLen(len(src)).
// Encode implements hexadecimal encoding.
func Encode(dst, src []byte) int {
@@ -105,7 +105,7 @@ func Dump(data []byte) string {
dumper := Dumper(&buf)
dumper.Write(data)
dumper.Close()
- return string(buf.Bytes())
+ return buf.String()
}
// Dumper returns a WriteCloser that writes a hex dump of all written data to
diff --git a/libgo/go/encoding/json/bench_test.go b/libgo/go/encoding/json/bench_test.go
index ed89d11..cd7380b 100644
--- a/libgo/go/encoding/json/bench_test.go
+++ b/libgo/go/encoding/json/bench_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -158,7 +158,7 @@ func BenchmarkCodeUnmarshal(b *testing.B) {
for i := 0; i < b.N; i++ {
var r codeResponse
if err := Unmarshal(codeJSON, &r); err != nil {
- b.Fatal("Unmmarshal:", err)
+ b.Fatal("Unmarshal:", err)
}
}
b.SetBytes(int64(len(codeJSON)))
@@ -173,7 +173,7 @@ func BenchmarkCodeUnmarshalReuse(b *testing.B) {
var r codeResponse
for i := 0; i < b.N; i++ {
if err := Unmarshal(codeJSON, &r); err != nil {
- b.Fatal("Unmmarshal:", err)
+ b.Fatal("Unmarshal:", err)
}
}
}
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 539d952..2eda875 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -29,9 +29,9 @@ import (
// with the following additional rules:
//
// To unmarshal JSON into a pointer, Unmarshal first handles the case of
-// the JSON being the JSON literal null. In that case, Unmarshal sets
-// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
-// the value pointed at by the pointer. If the pointer is nil, Unmarshal
+// the JSON being the JSON literal null. In that case, Unmarshal sets
+// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
+// the value pointed at by the pointer. If the pointer is nil, Unmarshal
// allocates a new value for it to point to.
//
// To unmarshal JSON into a struct, Unmarshal matches incoming object
@@ -61,10 +61,11 @@ import (
// If the JSON array is smaller than the Go array,
// the additional Go array elements are set to zero values.
//
-// To unmarshal a JSON object into a string-keyed map, Unmarshal first
-// establishes a map to use, If the map is nil, Unmarshal allocates a new map.
-// Otherwise Unmarshal reuses the existing map, keeping existing entries.
-// Unmarshal then stores key-value pairs from the JSON object into the map.
+// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
+// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
+// reuses the existing map, keeping existing entries. Unmarshal then stores key-
+// value pairs from the JSON object into the map. The map's key type must
+// either be a string, an integer, or implement encoding.TextUnmarshaler.
//
// If a JSON value is not appropriate for a given target type,
// or if a JSON number overflows the target type, Unmarshal
@@ -96,7 +97,7 @@ func Unmarshal(data []byte, v interface{}) error {
return d.unmarshal(v)
}
-// Unmarshaler is the interface implemented by objects
+// Unmarshaler is the interface implemented by types
// that can unmarshal a JSON description of themselves.
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
@@ -534,7 +535,7 @@ func (d *decodeState) array(v reflect.Value) {
if i < v.Len() {
if v.Kind() == reflect.Array {
- // Array. Zero the rest.
+ // Array. Zero the rest.
z := reflect.Zero(v.Type().Elem())
for ; i < v.Len(); i++ {
v.Index(i).Set(z)
@@ -549,6 +550,7 @@ func (d *decodeState) array(v reflect.Value) {
}
var nullLiteral = []byte("null")
+var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
// object consumes an object from d.data[d.off-1:], decoding into the value v.
// the first byte ('{') of the object has been read already.
@@ -577,16 +579,26 @@ func (d *decodeState) object(v reflect.Value) {
return
}
- // Check type of target: struct or map[string]T
+ // Check type of target:
+ // struct or
+ // map[T1]T2 where T1 is string, an integer type,
+ // or an encoding.TextUnmarshaler
switch v.Kind() {
case reflect.Map:
- // map must have string kind
+ // Map key must either have string kind, have an integer kind,
+ // or be an encoding.TextUnmarshaler.
t := v.Type()
- if t.Key().Kind() != reflect.String {
- d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
- d.off--
- d.next() // skip over { } in input
- return
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) {
+ d.saveError(&UnmarshalTypeError{"object", v.Type(), int64(d.off)})
+ d.off--
+ d.next() // skip over { } in input
+ return
+ }
}
if v.IsNil() {
v.Set(reflect.MakeMap(t))
@@ -687,7 +699,37 @@ func (d *decodeState) object(v reflect.Value) {
// Write value back to map;
// if using struct, subv points into struct already.
if v.Kind() == reflect.Map {
- kv := reflect.ValueOf(key).Convert(v.Type().Key())
+ kt := v.Type().Key()
+ var kv reflect.Value
+ switch {
+ case kt.Kind() == reflect.String:
+ kv = reflect.ValueOf(key).Convert(kt)
+ case reflect.PtrTo(kt).Implements(textUnmarshalerType):
+ kv = reflect.New(v.Type().Key())
+ d.literalStore(item, kv, true)
+ kv = kv.Elem()
+ default:
+ switch kt.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ s := string(key)
+ n, err := strconv.ParseInt(s, 10, 64)
+ if err != nil || reflect.Zero(kt).OverflowInt(n) {
+ d.saveError(&UnmarshalTypeError{"number " + s, kt, int64(start + 1)})
+ return
+ }
+ kv = reflect.ValueOf(n).Convert(kt)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ s := string(key)
+ n, err := strconv.ParseUint(s, 10, 64)
+ if err != nil || reflect.Zero(kt).OverflowUint(n) {
+ d.saveError(&UnmarshalTypeError{"number " + s, kt, int64(start + 1)})
+ return
+ }
+ kv = reflect.ValueOf(n).Convert(kt)
+ default:
+ panic("json: Unexpected key type") // should never occur
+ }
+ }
v.SetMapIndex(kv, subv)
}
@@ -902,7 +944,7 @@ func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool
}
// The xxxInterface routines build up a value to be stored
-// in an empty interface. They are not strictly necessary,
+// in an empty interface. They are not strictly necessary,
// but they avoid the weight of reflection in this common case.
// valueInterface is like value but returns interface{}
diff --git a/libgo/go/encoding/json/decode_test.go b/libgo/go/encoding/json/decode_test.go
index 9546ae4..255ff5c 100644
--- a/libgo/go/encoding/json/decode_test.go
+++ b/libgo/go/encoding/json/decode_test.go
@@ -7,10 +7,13 @@ package json
import (
"bytes"
"encoding"
+ "errors"
"fmt"
"image"
+ "math"
"net"
"reflect"
+ "strconv"
"strings"
"testing"
"time"
@@ -52,6 +55,8 @@ type tx struct {
x int
}
+type u8 uint8
+
// A type that can unmarshal itself.
type unmarshaler struct {
@@ -68,16 +73,20 @@ type ustruct struct {
}
type unmarshalerText struct {
- T bool
+ A, B string
}
// needed for re-marshaling tests
-func (u *unmarshalerText) MarshalText() ([]byte, error) {
- return []byte(""), nil
+func (u unmarshalerText) MarshalText() ([]byte, error) {
+ return []byte(u.A + ":" + u.B), nil
}
func (u *unmarshalerText) UnmarshalText(b []byte) error {
- *u = unmarshalerText{true} // All we need to see that UnmarshalText is called.
+ pos := bytes.Index(b, []byte(":"))
+ if pos == -1 {
+ return errors.New("missing separator")
+ }
+ u.A, u.B = string(b[:pos]), string(b[pos+1:])
return nil
}
@@ -87,6 +96,29 @@ type ustructText struct {
M unmarshalerText
}
+// u8marshal is an integer type that can marshal/unmarshal itself.
+type u8marshal uint8
+
+func (u8 u8marshal) MarshalText() ([]byte, error) {
+ return []byte(fmt.Sprintf("u%d", u8)), nil
+}
+
+var errMissingU8Prefix = errors.New("missing 'u' prefix")
+
+func (u8 *u8marshal) UnmarshalText(b []byte) error {
+ if !bytes.HasPrefix(b, []byte{'u'}) {
+ return errMissingU8Prefix
+ }
+ n, err := strconv.Atoi(string(b[1:]))
+ if err != nil {
+ return err
+ }
+ *u8 = u8marshal(n)
+ return nil
+}
+
+var _ encoding.TextUnmarshaler = (*u8marshal)(nil)
+
var (
um0, um1 unmarshaler // target2 of unmarshaling
ump = &um1
@@ -95,12 +127,16 @@ var (
umslicep = new([]unmarshaler)
umstruct = ustruct{unmarshaler{true}}
- um0T, um1T unmarshalerText // target2 of unmarshaling
- umpT = &um1T
- umtrueT = unmarshalerText{true}
- umsliceT = []unmarshalerText{{true}}
- umslicepT = new([]unmarshalerText)
- umstructT = ustructText{unmarshalerText{true}}
+ um0T, um1T unmarshalerText // target2 of unmarshaling
+ umpType = &um1T
+ umtrueXY = unmarshalerText{"x", "y"}
+ umsliceXY = []unmarshalerText{{"x", "y"}}
+ umslicepType = new([]unmarshalerText)
+ umstructType = new(ustructText)
+ umstructXY = ustructText{unmarshalerText{"x", "y"}}
+
+ ummapType = map[unmarshalerText]bool{}
+ ummapXY = map[unmarshalerText]bool{unmarshalerText{"x", "y"}: true}
)
// Test data structures for anonymous fields.
@@ -202,14 +238,6 @@ type S13 struct {
S8
}
-type unmarshalTest struct {
- in string
- ptr interface{}
- out interface{}
- err error
- useNumber bool
-}
-
type Ambig struct {
// Given "hello", the first match should win.
First int `json:"HELLO"`
@@ -225,6 +253,127 @@ type XYZ struct {
func sliceAddr(x []int) *[]int { return &x }
func mapAddr(x map[string]int) *map[string]int { return &x }
+type byteWithMarshalJSON byte
+
+func (b byteWithMarshalJSON) MarshalJSON() ([]byte, error) {
+ return []byte(fmt.Sprintf(`"Z%.2x"`, byte(b))), nil
+}
+
+func (b *byteWithMarshalJSON) UnmarshalJSON(data []byte) error {
+ if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' {
+ return fmt.Errorf("bad quoted string")
+ }
+ i, err := strconv.ParseInt(string(data[2:4]), 16, 8)
+ if err != nil {
+ return fmt.Errorf("bad hex")
+ }
+ *b = byteWithMarshalJSON(i)
+ return nil
+}
+
+type byteWithPtrMarshalJSON byte
+
+func (b *byteWithPtrMarshalJSON) MarshalJSON() ([]byte, error) {
+ return byteWithMarshalJSON(*b).MarshalJSON()
+}
+
+func (b *byteWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
+ return (*byteWithMarshalJSON)(b).UnmarshalJSON(data)
+}
+
+type byteWithMarshalText byte
+
+func (b byteWithMarshalText) MarshalText() ([]byte, error) {
+ return []byte(fmt.Sprintf(`Z%.2x`, byte(b))), nil
+}
+
+func (b *byteWithMarshalText) UnmarshalText(data []byte) error {
+ if len(data) != 3 || data[0] != 'Z' {
+ return fmt.Errorf("bad quoted string")
+ }
+ i, err := strconv.ParseInt(string(data[1:3]), 16, 8)
+ if err != nil {
+ return fmt.Errorf("bad hex")
+ }
+ *b = byteWithMarshalText(i)
+ return nil
+}
+
+type byteWithPtrMarshalText byte
+
+func (b *byteWithPtrMarshalText) MarshalText() ([]byte, error) {
+ return byteWithMarshalText(*b).MarshalText()
+}
+
+func (b *byteWithPtrMarshalText) UnmarshalText(data []byte) error {
+ return (*byteWithMarshalText)(b).UnmarshalText(data)
+}
+
+type intWithMarshalJSON int
+
+func (b intWithMarshalJSON) MarshalJSON() ([]byte, error) {
+ return []byte(fmt.Sprintf(`"Z%.2x"`, int(b))), nil
+}
+
+func (b *intWithMarshalJSON) UnmarshalJSON(data []byte) error {
+ if len(data) != 5 || data[0] != '"' || data[1] != 'Z' || data[4] != '"' {
+ return fmt.Errorf("bad quoted string")
+ }
+ i, err := strconv.ParseInt(string(data[2:4]), 16, 8)
+ if err != nil {
+ return fmt.Errorf("bad hex")
+ }
+ *b = intWithMarshalJSON(i)
+ return nil
+}
+
+type intWithPtrMarshalJSON int
+
+func (b *intWithPtrMarshalJSON) MarshalJSON() ([]byte, error) {
+ return intWithMarshalJSON(*b).MarshalJSON()
+}
+
+func (b *intWithPtrMarshalJSON) UnmarshalJSON(data []byte) error {
+ return (*intWithMarshalJSON)(b).UnmarshalJSON(data)
+}
+
+type intWithMarshalText int
+
+func (b intWithMarshalText) MarshalText() ([]byte, error) {
+ return []byte(fmt.Sprintf(`Z%.2x`, int(b))), nil
+}
+
+func (b *intWithMarshalText) UnmarshalText(data []byte) error {
+ if len(data) != 3 || data[0] != 'Z' {
+ return fmt.Errorf("bad quoted string")
+ }
+ i, err := strconv.ParseInt(string(data[1:3]), 16, 8)
+ if err != nil {
+ return fmt.Errorf("bad hex")
+ }
+ *b = intWithMarshalText(i)
+ return nil
+}
+
+type intWithPtrMarshalText int
+
+func (b *intWithPtrMarshalText) MarshalText() ([]byte, error) {
+ return intWithMarshalText(*b).MarshalText()
+}
+
+func (b *intWithPtrMarshalText) UnmarshalText(data []byte) error {
+ return (*intWithMarshalText)(b).UnmarshalText(data)
+}
+
+type unmarshalTest struct {
+ in string
+ ptr interface{}
+ out interface{}
+ err error
+ useNumber bool
+ golden bool
+}
+
var unmarshalTests = []unmarshalTest{
// basic types
{in: `true`, ptr: new(bool), out: true},
@@ -302,14 +451,81 @@ var unmarshalTests = []unmarshalTest{
{in: `{"T":false}`, ptr: &ump, out: &umtrue},
{in: `[{"T":false}]`, ptr: &umslice, out: umslice},
{in: `[{"T":false}]`, ptr: &umslicep, out: &umslice},
- {in: `{"M":{"T":false}}`, ptr: &umstruct, out: umstruct},
+ {in: `{"M":{"T":"x:y"}}`, ptr: &umstruct, out: umstruct},
// UnmarshalText interface test
- {in: `"X"`, ptr: &um0T, out: umtrueT}, // use "false" so test will fail if custom unmarshaler is not called
- {in: `"X"`, ptr: &umpT, out: &umtrueT},
- {in: `["X"]`, ptr: &umsliceT, out: umsliceT},
- {in: `["X"]`, ptr: &umslicepT, out: &umsliceT},
- {in: `{"M":"X"}`, ptr: &umstructT, out: umstructT},
+ {in: `"x:y"`, ptr: &um0T, out: umtrueXY},
+ {in: `"x:y"`, ptr: &umpType, out: &umtrueXY},
+ {in: `["x:y"]`, ptr: &umsliceXY, out: umsliceXY},
+ {in: `["x:y"]`, ptr: &umslicepType, out: &umsliceXY},
+ {in: `{"M":"x:y"}`, ptr: umstructType, out: umstructXY},
+
+ // integer-keyed map test
+ {
+ in: `{"-1":"a","0":"b","1":"c"}`,
+ ptr: new(map[int]string),
+ out: map[int]string{-1: "a", 0: "b", 1: "c"},
+ },
+ {
+ in: `{"0":"a","10":"c","9":"b"}`,
+ ptr: new(map[u8]string),
+ out: map[u8]string{0: "a", 9: "b", 10: "c"},
+ },
+ {
+ in: `{"-9223372036854775808":"min","9223372036854775807":"max"}`,
+ ptr: new(map[int64]string),
+ out: map[int64]string{math.MinInt64: "min", math.MaxInt64: "max"},
+ },
+ {
+ in: `{"18446744073709551615":"max"}`,
+ ptr: new(map[uint64]string),
+ out: map[uint64]string{math.MaxUint64: "max"},
+ },
+ {
+ in: `{"0":false,"10":true}`,
+ ptr: new(map[uintptr]bool),
+ out: map[uintptr]bool{0: false, 10: true},
+ },
+
+ // Check that MarshalText and UnmarshalText take precedence
+ // over default integer handling in map keys.
+ {
+ in: `{"u2":4}`,
+ ptr: new(map[u8marshal]int),
+ out: map[u8marshal]int{2: 4},
+ },
+ {
+ in: `{"2":4}`,
+ ptr: new(map[u8marshal]int),
+ err: errMissingU8Prefix,
+ },
+
+ // integer-keyed map errors
+ {
+ in: `{"abc":"abc"}`,
+ ptr: new(map[int]string),
+ err: &UnmarshalTypeError{"number abc", reflect.TypeOf(0), 2},
+ },
+ {
+ in: `{"256":"abc"}`,
+ ptr: new(map[uint8]string),
+ err: &UnmarshalTypeError{"number 256", reflect.TypeOf(uint8(0)), 2},
+ },
+ {
+ in: `{"128":"abc"}`,
+ ptr: new(map[int8]string),
+ err: &UnmarshalTypeError{"number 128", reflect.TypeOf(int8(0)), 2},
+ },
+ {
+ in: `{"-1":"abc"}`,
+ ptr: new(map[uint8]string),
+ err: &UnmarshalTypeError{"number -1", reflect.TypeOf(uint8(0)), 2},
+ },
+
+ // Map keys can be encoding.TextUnmarshalers.
+ {in: `{"x:y":true}`, ptr: &ummapType, out: ummapXY},
+ // If multiple values for the same key exists, only the most recent value is used.
+ {in: `{"x:y":false,"x:y":true}`, ptr: &ummapType, out: ummapXY},
// Overwriting of data.
// This is different from package xml, but it's what we've always done.
@@ -426,11 +642,101 @@ var unmarshalTests = []unmarshalTest{
out: "hello\ufffd\ufffd\ufffd\ufffd\ufffd\ufffdworld",
},
- // issue 8305
+ // Used to be issue 8305, but time.Time implements encoding.TextUnmarshaler so this works now.
{
in: `{"2009-11-10T23:00:00Z": "hello world"}`,
ptr: &map[time.Time]string{},
- err: &UnmarshalTypeError{"object", reflect.TypeOf(map[time.Time]string{}), 1},
+ out: map[time.Time]string{time.Date(2009, 11, 10, 23, 0, 0, 0, time.UTC): "hello world"},
+ },
+
+ // issue 8305
+ {
+ in: `{"2009-11-10T23:00:00Z": "hello world"}`,
+ ptr: &map[Point]string{},
+ err: &UnmarshalTypeError{"object", reflect.TypeOf(map[Point]string{}), 1},
+ },
+ {
+ in: `{"asdf": "hello world"}`,
+ ptr: &map[unmarshaler]string{},
+ err: &UnmarshalTypeError{"object", reflect.TypeOf(map[unmarshaler]string{}), 1},
+ },
+
+ // related to issue 13783.
+ // Go 1.7 changed marshaling a slice of typed byte to use the methods on the byte type,
+ // similar to marshaling a slice of typed int.
+ // These tests check that, assuming the byte type also has valid decoding methods,
+ // either the old base64 string encoding or the new per-element encoding can be
+ // successfully unmarshaled. The custom unmarshalers were accessible in earlier
+ // versions of Go, even though the custom marshaler was not.
+ {
+ in: `"AQID"`,
+ ptr: new([]byteWithMarshalJSON),
+ out: []byteWithMarshalJSON{1, 2, 3},
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]byteWithMarshalJSON),
+ out: []byteWithMarshalJSON{1, 2, 3},
+ golden: true,
+ },
+ {
+ in: `"AQID"`,
+ ptr: new([]byteWithMarshalText),
+ out: []byteWithMarshalText{1, 2, 3},
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]byteWithMarshalText),
+ out: []byteWithMarshalText{1, 2, 3},
+ golden: true,
+ },
+ {
+ in: `"AQID"`,
+ ptr: new([]byteWithPtrMarshalJSON),
+ out: []byteWithPtrMarshalJSON{1, 2, 3},
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]byteWithPtrMarshalJSON),
+ out: []byteWithPtrMarshalJSON{1, 2, 3},
+ golden: true,
+ },
+ {
+ in: `"AQID"`,
+ ptr: new([]byteWithPtrMarshalText),
+ out: []byteWithPtrMarshalText{1, 2, 3},
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]byteWithPtrMarshalText),
+ out: []byteWithPtrMarshalText{1, 2, 3},
+ golden: true,
+ },
+
+ // ints work with the marshaler but not the base64 []byte case
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]intWithMarshalJSON),
+ out: []intWithMarshalJSON{1, 2, 3},
+ golden: true,
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]intWithMarshalText),
+ out: []intWithMarshalText{1, 2, 3},
+ golden: true,
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]intWithPtrMarshalJSON),
+ out: []intWithPtrMarshalJSON{1, 2, 3},
+ golden: true,
+ },
+ {
+ in: `["Z01","Z02","Z03"]`,
+ ptr: new([]intWithPtrMarshalText),
+ out: []intWithPtrMarshalText{1, 2, 3},
+ golden: true,
},
}
@@ -565,13 +871,16 @@ func TestUnmarshal(t *testing.T) {
continue
}
- // Check round trip.
+ // Check round trip also decodes correctly.
if tt.err == nil {
enc, err := Marshal(v.Interface())
if err != nil {
t.Errorf("#%d: error re-marshaling: %v", i, err)
continue
}
+ if tt.golden && !bytes.Equal(enc, in) {
+ t.Errorf("#%d: remarshal mismatch:\nhave: %s\nwant: %s", i, enc, in)
+ }
vv := reflect.New(reflect.TypeOf(tt.ptr).Elem())
dec = NewDecoder(bytes.NewReader(enc))
if tt.useNumber {
@@ -1270,7 +1579,7 @@ func TestSliceOfCustomByte(t *testing.T) {
t.Fatal(err)
}
if !reflect.DeepEqual(a, b) {
- t.Fatal("expected %v == %v", a, b)
+ t.Fatalf("expected %v == %v", a, b)
}
}
diff --git a/libgo/go/encoding/json/encode.go b/libgo/go/encoding/json/encode.go
index 69ac7e0..6bb6de8 100644
--- a/libgo/go/encoding/json/encode.go
+++ b/libgo/go/encoding/json/encode.go
@@ -1,9 +1,9 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package json implements encoding and decoding of JSON objects as defined in
-// RFC 4627. The mapping between JSON objects and Go values is described
+// Package json implements encoding and decoding of JSON as defined in
+// RFC 4627. The mapping between JSON and Go values is described
// in the documentation for the Marshal and Unmarshal functions.
//
// See "JSON and Go" for an introduction to this package:
@@ -22,6 +22,7 @@ import (
"strconv"
"strings"
"sync"
+ "sync/atomic"
"unicode"
"unicode/utf8"
)
@@ -49,10 +50,11 @@ import (
// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
// to keep some browsers from misinterpreting JSON output as HTML.
// Ampersand "&" is also escaped to "\u0026" for the same reason.
+// This escaping can be disabled using an Encoder with DisableHTMLEscaping.
//
// Array and slice values encode as JSON arrays, except that
// []byte encodes as a base64-encoded string, and a nil slice
-// encodes as the null JSON object.
+// encodes as the null JSON value.
//
// Struct values encode as JSON objects. Each exported struct field
// becomes a member of the object unless
@@ -89,8 +91,8 @@ import (
// Int64String int64 `json:",string"`
//
// The key name will be used if it's a non-empty string consisting of
-// only Unicode letters, digits, dollar signs, percent signs, hyphens,
-// underscores and slashes.
+// only Unicode letters, digits, and ASCII punctuation except quotation
+// marks, backslash, and comma.
//
// Anonymous struct fields are usually marshaled as if their inner exported fields
// were fields in the outer struct, subject to the usual Go visibility rules amended
@@ -116,27 +118,31 @@ import (
// an anonymous struct field in both current and earlier versions, give the field
// a JSON tag of "-".
//
-// Map values encode as JSON objects.
-// The map's key type must be string; the map keys are used as JSON object
-// keys, subject to the UTF-8 coercion described for string values above.
+// Map values encode as JSON objects. The map's key type must either be a
+// string, an integer type, or implement encoding.TextMarshaler. The map keys
+// are sorted and used as JSON object keys by applying the following rules,
+// subject to the UTF-8 coercion described for string values above:
+// - string keys are used directly
+// - encoding.TextMarshalers are marshaled
+// - integer keys are converted to strings
//
// Pointer values encode as the value pointed to.
-// A nil pointer encodes as the null JSON object.
+// A nil pointer encodes as the null JSON value.
//
// Interface values encode as the value contained in the interface.
-// A nil interface value encodes as the null JSON object.
+// A nil interface value encodes as the null JSON value.
//
// Channel, complex, and function values cannot be encoded in JSON.
// Attempting to encode such a value causes Marshal to return
// an UnsupportedTypeError.
//
// JSON cannot represent cyclic data structures and Marshal does not
-// handle them. Passing cyclic structures to Marshal will result in
+// handle them. Passing cyclic structures to Marshal will result in
// an infinite recursion.
//
func Marshal(v interface{}) ([]byte, error) {
e := &encodeState{}
- err := e.marshal(v)
+ err := e.marshal(v, encOpts{escapeHTML: true})
if err != nil {
return nil, err
}
@@ -192,7 +198,7 @@ func HTMLEscape(dst *bytes.Buffer, src []byte) {
}
}
-// Marshaler is the interface implemented by objects that
+// Marshaler is the interface implemented by types that
// can marshal themselves into valid JSON.
type Marshaler interface {
MarshalJSON() ([]byte, error)
@@ -259,7 +265,7 @@ func newEncodeState() *encodeState {
return new(encodeState)
}
-func (e *encodeState) marshal(v interface{}) (err error) {
+func (e *encodeState) marshal(v interface{}, opts encOpts) (err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
@@ -271,7 +277,7 @@ func (e *encodeState) marshal(v interface{}) (err error) {
err = r.(error)
}
}()
- e.reflectValue(reflect.ValueOf(v))
+ e.reflectValue(reflect.ValueOf(v), opts)
return nil
}
@@ -297,11 +303,18 @@ func isEmptyValue(v reflect.Value) bool {
return false
}
-func (e *encodeState) reflectValue(v reflect.Value) {
- valueEncoder(v)(e, v, false)
+func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
+ valueEncoder(v)(e, v, opts)
}
-type encoderFunc func(e *encodeState, v reflect.Value, quoted bool)
+type encOpts struct {
+ // quoted causes primitive fields to be encoded inside JSON strings.
+ quoted bool
+ // escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
+ escapeHTML bool
+}
+
+type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
var encoderCache struct {
sync.RWMutex
@@ -325,7 +338,7 @@ func typeEncoder(t reflect.Type) encoderFunc {
// To deal with recursive types, populate the map with an
// indirect func before we build it. This type waits on the
- // real func (f) to be ready and then calls it. This indirect
+ // real func (f) to be ready and then calls it. This indirect
// func is only used for recursive types.
encoderCache.Lock()
if encoderCache.m == nil {
@@ -333,9 +346,9 @@ func typeEncoder(t reflect.Type) encoderFunc {
}
var wg sync.WaitGroup
wg.Add(1)
- encoderCache.m[t] = func(e *encodeState, v reflect.Value, quoted bool) {
+ encoderCache.m[t] = func(e *encodeState, v reflect.Value, opts encOpts) {
wg.Wait()
- f(e, v, quoted)
+ f(e, v, opts)
}
encoderCache.Unlock()
@@ -405,11 +418,11 @@ func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
}
}
-func invalidValueEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
e.WriteString("null")
}
-func marshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
if v.Kind() == reflect.Ptr && v.IsNil() {
e.WriteString("null")
return
@@ -418,14 +431,14 @@ func marshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
b, err := m.MarshalJSON()
if err == nil {
// copy JSON into buffer, checking validity.
- err = compact(&e.Buffer, b, true)
+ err = compact(&e.Buffer, b, opts.escapeHTML)
}
if err != nil {
e.error(&MarshalerError{v.Type(), err})
}
}
-func addrMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func addrMarshalerEncoder(e *encodeState, v reflect.Value, _ encOpts) {
va := v.Addr()
if va.IsNil() {
e.WriteString("null")
@@ -442,7 +455,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
}
}
-func textMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
if v.Kind() == reflect.Ptr && v.IsNil() {
e.WriteString("null")
return
@@ -452,10 +465,10 @@ func textMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
if err != nil {
e.error(&MarshalerError{v.Type(), err})
}
- e.stringBytes(b)
+ e.stringBytes(b, opts.escapeHTML)
}
-func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
va := v.Addr()
if va.IsNil() {
e.WriteString("null")
@@ -466,11 +479,11 @@ func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, quoted bool) {
if err != nil {
e.error(&MarshalerError{v.Type(), err})
}
- e.stringBytes(b)
+ e.stringBytes(b, opts.escapeHTML)
}
-func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
- if quoted {
+func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ if opts.quoted {
e.WriteByte('"')
}
if v.Bool() {
@@ -478,46 +491,46 @@ func boolEncoder(e *encodeState, v reflect.Value, quoted bool) {
} else {
e.WriteString("false")
}
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
}
-func intEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
b := strconv.AppendInt(e.scratch[:0], v.Int(), 10)
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
e.Write(b)
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
}
-func uintEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
b := strconv.AppendUint(e.scratch[:0], v.Uint(), 10)
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
e.Write(b)
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
}
type floatEncoder int // number of bits
-func (bits floatEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
f := v.Float()
if math.IsInf(f, 0) || math.IsNaN(f) {
e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
}
b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, int(bits))
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
e.Write(b)
- if quoted {
+ if opts.quoted {
e.WriteByte('"')
}
}
@@ -527,7 +540,7 @@ var (
float64Encoder = (floatEncoder(64)).encode
)
-func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
if v.Type() == numberType {
numStr := v.String()
// In Go1.5 the empty string encodes to "0", while this is not a valid number literal
@@ -541,26 +554,26 @@ func stringEncoder(e *encodeState, v reflect.Value, quoted bool) {
e.WriteString(numStr)
return
}
- if quoted {
+ if opts.quoted {
sb, err := Marshal(v.String())
if err != nil {
e.error(err)
}
- e.string(string(sb))
+ e.string(string(sb), opts.escapeHTML)
} else {
- e.string(v.String())
+ e.string(v.String(), opts.escapeHTML)
}
}
-func interfaceEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
return
}
- e.reflectValue(v.Elem())
+ e.reflectValue(v.Elem(), opts)
}
-func unsupportedTypeEncoder(e *encodeState, v reflect.Value, quoted bool) {
+func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
e.error(&UnsupportedTypeError{v.Type()})
}
@@ -569,7 +582,7 @@ type structEncoder struct {
fieldEncs []encoderFunc
}
-func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+func (se *structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
e.WriteByte('{')
first := true
for i, f := range se.fields {
@@ -582,9 +595,10 @@ func (se *structEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
} else {
e.WriteByte(',')
}
- e.string(f.name)
+ e.string(f.name, opts.escapeHTML)
e.WriteByte(':')
- se.fieldEncs[i](e, fv, f.quoted)
+ opts.quoted = f.quoted
+ se.fieldEncs[i](e, fv, opts)
}
e.WriteByte('}')
}
@@ -605,34 +619,50 @@ type mapEncoder struct {
elemEnc encoderFunc
}
-func (me *mapEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+func (me *mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
return
}
e.WriteByte('{')
- var sv stringValues = v.MapKeys()
- sort.Sort(sv)
- for i, k := range sv {
+
+ // Extract and sort the keys.
+ keys := v.MapKeys()
+ sv := make([]reflectWithString, len(keys))
+ for i, v := range keys {
+ sv[i].v = v
+ if err := sv[i].resolve(); err != nil {
+ e.error(&MarshalerError{v.Type(), err})
+ }
+ }
+ sort.Sort(byString(sv))
+
+ for i, kv := range sv {
if i > 0 {
e.WriteByte(',')
}
- e.string(k.String())
+ e.string(kv.s, opts.escapeHTML)
e.WriteByte(':')
- me.elemEnc(e, v.MapIndex(k), false)
+ me.elemEnc(e, v.MapIndex(kv.v), opts)
}
e.WriteByte('}')
}
func newMapEncoder(t reflect.Type) encoderFunc {
- if t.Key().Kind() != reflect.String {
- return unsupportedTypeEncoder
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !t.Key().Implements(textMarshalerType) {
+ return unsupportedTypeEncoder
+ }
}
me := &mapEncoder{typeEncoder(t.Elem())}
return me.encode
}
-func encodeByteSlice(e *encodeState, v reflect.Value, _ bool) {
+func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
if v.IsNil() {
e.WriteString("null")
return
@@ -659,18 +689,21 @@ type sliceEncoder struct {
arrayEnc encoderFunc
}
-func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+func (se *sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
return
}
- se.arrayEnc(e, v, false)
+ se.arrayEnc(e, v, opts)
}
func newSliceEncoder(t reflect.Type) encoderFunc {
// Byte slices get special treatment; arrays don't.
if t.Elem().Kind() == reflect.Uint8 {
- return encodeByteSlice
+ p := reflect.PtrTo(t.Elem())
+ if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
+ return encodeByteSlice
+ }
}
enc := &sliceEncoder{newArrayEncoder(t)}
return enc.encode
@@ -680,14 +713,14 @@ type arrayEncoder struct {
elemEnc encoderFunc
}
-func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, _ bool) {
+func (ae *arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
e.WriteByte('[')
n := v.Len()
for i := 0; i < n; i++ {
if i > 0 {
e.WriteByte(',')
}
- ae.elemEnc(e, v.Index(i), false)
+ ae.elemEnc(e, v.Index(i), opts)
}
e.WriteByte(']')
}
@@ -701,12 +734,12 @@ type ptrEncoder struct {
elemEnc encoderFunc
}
-func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+func (pe *ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if v.IsNil() {
e.WriteString("null")
return
}
- pe.elemEnc(e, v.Elem(), quoted)
+ pe.elemEnc(e, v.Elem(), opts)
}
func newPtrEncoder(t reflect.Type) encoderFunc {
@@ -718,11 +751,11 @@ type condAddrEncoder struct {
canAddrEnc, elseEnc encoderFunc
}
-func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, quoted bool) {
+func (ce *condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
if v.CanAddr() {
- ce.canAddrEnc(e, v, quoted)
+ ce.canAddrEnc(e, v, opts)
} else {
- ce.elseEnc(e, v, quoted)
+ ce.elseEnc(e, v, opts)
}
}
@@ -775,23 +808,50 @@ func typeByIndex(t reflect.Type, index []int) reflect.Type {
return t
}
-// stringValues is a slice of reflect.Value holding *reflect.StringValue.
+type reflectWithString struct {
+ v reflect.Value
+ s string
+}
+
+func (w *reflectWithString) resolve() error {
+ if w.v.Kind() == reflect.String {
+ w.s = w.v.String()
+ return nil
+ }
+ if tm, ok := w.v.Interface().(encoding.TextMarshaler); ok {
+ buf, err := tm.MarshalText()
+ w.s = string(buf)
+ return err
+ }
+ switch w.v.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ w.s = strconv.FormatInt(w.v.Int(), 10)
+ return nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ w.s = strconv.FormatUint(w.v.Uint(), 10)
+ return nil
+ }
+ panic("unexpected map key type")
+}
+
+// byString is a slice of reflectWithString where the reflect.Value is either
+// a string or an encoding.TextMarshaler.
// It implements the methods to sort by string.
-type stringValues []reflect.Value
+type byString []reflectWithString
-func (sv stringValues) Len() int { return len(sv) }
-func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
-func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
-func (sv stringValues) get(i int) string { return sv[i].String() }
+func (sv byString) Len() int { return len(sv) }
+func (sv byString) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
+func (sv byString) Less(i, j int) bool { return sv[i].s < sv[j].s }
// NOTE: keep in sync with stringBytes below.
-func (e *encodeState) string(s string) int {
+func (e *encodeState) string(s string, escapeHTML bool) int {
len0 := e.Len()
e.WriteByte('"')
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
- if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
+ if 0x20 <= b && b != '\\' && b != '"' &&
+ (!escapeHTML || b != '<' && b != '>' && b != '&') {
i++
continue
}
@@ -812,10 +872,11 @@ func (e *encodeState) string(s string) int {
e.WriteByte('\\')
e.WriteByte('t')
default:
- // This encodes bytes < 0x20 except for \n and \r,
- // as well as <, > and &. The latter are escaped because they
- // can lead to security holes when user-controlled strings
- // are rendered into JSON and served to some browsers.
+ // This encodes bytes < 0x20 except for \t, \n and \r.
+ // If escapeHTML is set, it also escapes <, >, and &
+ // because they can lead to security holes when
+ // user-controlled strings are rendered into JSON
+ // and served to some browsers.
e.WriteString(`\u00`)
e.WriteByte(hex[b>>4])
e.WriteByte(hex[b&0xF])
@@ -861,13 +922,14 @@ func (e *encodeState) string(s string) int {
}
// NOTE: keep in sync with string above.
-func (e *encodeState) stringBytes(s []byte) int {
+func (e *encodeState) stringBytes(s []byte, escapeHTML bool) int {
len0 := e.Len()
e.WriteByte('"')
start := 0
for i := 0; i < len(s); {
if b := s[i]; b < utf8.RuneSelf {
- if 0x20 <= b && b != '\\' && b != '"' && b != '<' && b != '>' && b != '&' {
+ if 0x20 <= b && b != '\\' && b != '"' &&
+ (!escapeHTML || b != '<' && b != '>' && b != '&') {
i++
continue
}
@@ -888,10 +950,11 @@ func (e *encodeState) stringBytes(s []byte) int {
e.WriteByte('\\')
e.WriteByte('t')
default:
- // This encodes bytes < 0x20 except for \n and \r,
- // as well as <, >, and &. The latter are escaped because they
- // can lead to security holes when user-controlled strings
- // are rendered into JSON and served to some browsers.
+ // This encodes bytes < 0x20 except for \t, \n and \r.
+ // If escapeHTML is set, it also escapes <, >, and &
+ // because they can lead to security holes when
+ // user-controlled strings are rendered into JSON
+ // and served to some browsers.
e.WriteString(`\u00`)
e.WriteByte(hex[b>>4])
e.WriteByte(hex[b&0xF])
@@ -1169,15 +1232,14 @@ func dominantField(fields []field) (field, bool) {
}
var fieldCache struct {
- sync.RWMutex
- m map[reflect.Type][]field
+ value atomic.Value // map[reflect.Type][]field
+ mu sync.Mutex // used only by writers
}
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
func cachedTypeFields(t reflect.Type) []field {
- fieldCache.RLock()
- f := fieldCache.m[t]
- fieldCache.RUnlock()
+ m, _ := fieldCache.value.Load().(map[reflect.Type][]field)
+ f := m[t]
if f != nil {
return f
}
@@ -1189,11 +1251,14 @@ func cachedTypeFields(t reflect.Type) []field {
f = []field{}
}
- fieldCache.Lock()
- if fieldCache.m == nil {
- fieldCache.m = map[reflect.Type][]field{}
+ fieldCache.mu.Lock()
+ m, _ = fieldCache.value.Load().(map[reflect.Type][]field)
+ newM := make(map[reflect.Type][]field, len(m)+1)
+ for k, v := range m {
+ newM[k] = v
}
- fieldCache.m[t] = f
- fieldCache.Unlock()
+ newM[t] = f
+ fieldCache.value.Store(newM)
+ fieldCache.mu.Unlock()
return f
}
diff --git a/libgo/go/encoding/json/encode_test.go b/libgo/go/encoding/json/encode_test.go
index c00491e..b484022 100644
--- a/libgo/go/encoding/json/encode_test.go
+++ b/libgo/go/encoding/json/encode_test.go
@@ -6,6 +6,7 @@ package json
import (
"bytes"
+ "fmt"
"math"
"reflect"
"testing"
@@ -375,41 +376,45 @@ func TestDuplicatedFieldDisappears(t *testing.T) {
func TestStringBytes(t *testing.T) {
// Test that encodeState.stringBytes and encodeState.string use the same encoding.
- es := &encodeState{}
var r []rune
for i := '\u0000'; i <= unicode.MaxRune; i++ {
r = append(r, i)
}
s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too
- es.string(s)
- esBytes := &encodeState{}
- esBytes.stringBytes([]byte(s))
+ for _, escapeHTML := range []bool{true, false} {
+ es := &encodeState{}
+ es.string(s, escapeHTML)
- enc := es.Buffer.String()
- encBytes := esBytes.Buffer.String()
- if enc != encBytes {
- i := 0
- for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
- i++
- }
- enc = enc[i:]
- encBytes = encBytes[i:]
- i = 0
- for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
- i++
- }
- enc = enc[:len(enc)-i]
- encBytes = encBytes[:len(encBytes)-i]
+ esBytes := &encodeState{}
+ esBytes.stringBytes([]byte(s), escapeHTML)
- if len(enc) > 20 {
- enc = enc[:20] + "..."
- }
- if len(encBytes) > 20 {
- encBytes = encBytes[:20] + "..."
- }
+ enc := es.Buffer.String()
+ encBytes := esBytes.Buffer.String()
+ if enc != encBytes {
+ i := 0
+ for i < len(enc) && i < len(encBytes) && enc[i] == encBytes[i] {
+ i++
+ }
+ enc = enc[i:]
+ encBytes = encBytes[i:]
+ i = 0
+ for i < len(enc) && i < len(encBytes) && enc[len(enc)-i-1] == encBytes[len(encBytes)-i-1] {
+ i++
+ }
+ enc = enc[:len(enc)-i]
+ encBytes = encBytes[:len(encBytes)-i]
+
+ if len(enc) > 20 {
+ enc = enc[:20] + "..."
+ }
+ if len(encBytes) > 20 {
+ encBytes = encBytes[:20] + "..."
+ }
- t.Errorf("encodings differ at %#q vs %#q", enc, encBytes)
+ t.Errorf("with escapeHTML=%t, encodings differ at %#q vs %#q",
+ escapeHTML, enc, encBytes)
+ }
}
}
@@ -536,3 +541,73 @@ func TestEncodeString(t *testing.T) {
}
}
}
+
+type jsonbyte byte
+
+func (b jsonbyte) MarshalJSON() ([]byte, error) { return tenc(`{"JB":%d}`, b) }
+
+type textbyte byte
+
+func (b textbyte) MarshalText() ([]byte, error) { return tenc(`TB:%d`, b) }
+
+type jsonint int
+
+func (i jsonint) MarshalJSON() ([]byte, error) { return tenc(`{"JI":%d}`, i) }
+
+type textint int
+
+func (i textint) MarshalText() ([]byte, error) { return tenc(`TI:%d`, i) }
+
+func tenc(format string, a ...interface{}) ([]byte, error) {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, format, a...)
+ return buf.Bytes(), nil
+}
+
+// Issue 13783
+func TestEncodeBytekind(t *testing.T) {
+ testdata := []struct {
+ data interface{}
+ want string
+ }{
+ {byte(7), "7"},
+ {jsonbyte(7), `{"JB":7}`},
+ {textbyte(4), `"TB:4"`},
+ {jsonint(5), `{"JI":5}`},
+ {textint(1), `"TI:1"`},
+ {[]byte{0, 1}, `"AAE="`},
+ {[]jsonbyte{0, 1}, `[{"JB":0},{"JB":1}]`},
+ {[][]jsonbyte{{0, 1}, {3}}, `[[{"JB":0},{"JB":1}],[{"JB":3}]]`},
+ {[]textbyte{2, 3}, `["TB:2","TB:3"]`},
+ {[]jsonint{5, 4}, `[{"JI":5},{"JI":4}]`},
+ {[]textint{9, 3}, `["TI:9","TI:3"]`},
+ {[]int{9, 3}, `[9,3]`},
+ }
+ for _, d := range testdata {
+ js, err := Marshal(d.data)
+ if err != nil {
+ t.Error(err)
+ continue
+ }
+ got, want := string(js), d.want
+ if got != want {
+ t.Errorf("got %s, want %s", got, want)
+ }
+ }
+}
+
+func TestTextMarshalerMapKeysAreSorted(t *testing.T) {
+ b, err := Marshal(map[unmarshalerText]int{
+ {"x", "y"}: 1,
+ {"y", "x"}: 2,
+ {"a", "z"}: 3,
+ {"z", "a"}: 4,
+ })
+ if err != nil {
+ t.Fatalf("Failed to Marshal text.Marshaler: %v", err)
+ }
+ const want = `{"a:z":3,"x:y":1,"y:x":2,"z:a":4}`
+ if string(b) != want {
+ t.Errorf("Marshal map with text.Marshaler keys: got %#q, want %#q", b, want)
+ }
+}
diff --git a/libgo/go/encoding/json/indent.go b/libgo/go/encoding/json/indent.go
index 7cd9f4d..fba1954 100644
--- a/libgo/go/encoding/json/indent.go
+++ b/libgo/go/encoding/json/indent.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/json/number_test.go b/libgo/go/encoding/json/number_test.go
index 4e63cf9..4b86999 100644
--- a/libgo/go/encoding/json/number_test.go
+++ b/libgo/go/encoding/json/number_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/json/scanner.go b/libgo/go/encoding/json/scanner.go
index ee6622e..a6d8706 100644
--- a/libgo/go/encoding/json/scanner.go
+++ b/libgo/go/encoding/json/scanner.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -132,7 +132,7 @@ const (
// These values are stored in the parseState stack.
// They give the current state of a composite value
-// being scanned. If the parser is inside a nested value
+// being scanned. If the parser is inside a nested value
// the parseState describes the nested state, outermost at entry 0.
const (
parseObjectKey = iota // parsing object key (before colon)
diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go
index 66383ef..70a2897 100644
--- a/libgo/go/encoding/json/scanner_test.go
+++ b/libgo/go/encoding/json/scanner_test.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/json/stream.go b/libgo/go/encoding/json/stream.go
index 8ddcf4d..87f0e57 100644
--- a/libgo/go/encoding/json/stream.go
+++ b/libgo/go/encoding/json/stream.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -10,7 +10,7 @@ import (
"io"
)
-// A Decoder reads and decodes JSON objects from an input stream.
+// A Decoder reads and decodes JSON values from an input stream.
type Decoder struct {
r io.Reader
buf []byte
@@ -148,7 +148,7 @@ func (dec *Decoder) refill() error {
dec.buf = newBuf
}
- // Read. Delay error for next iteration (after scan).
+ // Read. Delay error for next iteration (after scan).
n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
dec.buf = dec.buf[0 : len(dec.buf)+n]
@@ -164,15 +164,20 @@ func nonSpace(b []byte) bool {
return false
}
-// An Encoder writes JSON objects to an output stream.
+// An Encoder writes JSON values to an output stream.
type Encoder struct {
- w io.Writer
- err error
+ w io.Writer
+ err error
+ escapeHTML bool
+
+ indentBuf *bytes.Buffer
+ indentPrefix string
+ indentValue string
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
- return &Encoder{w: w}
+ return &Encoder{w: w, escapeHTML: true}
}
// Encode writes the JSON encoding of v to the stream,
@@ -185,7 +190,7 @@ func (enc *Encoder) Encode(v interface{}) error {
return enc.err
}
e := newEncodeState()
- err := e.marshal(v)
+ err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML})
if err != nil {
return err
}
@@ -198,14 +203,45 @@ func (enc *Encoder) Encode(v interface{}) error {
// digits coming.
e.WriteByte('\n')
- if _, err = enc.w.Write(e.Bytes()); err != nil {
+ b := e.Bytes()
+ if enc.indentPrefix != "" || enc.indentValue != "" {
+ if enc.indentBuf == nil {
+ enc.indentBuf = new(bytes.Buffer)
+ }
+ enc.indentBuf.Reset()
+ err = Indent(enc.indentBuf, b, enc.indentPrefix, enc.indentValue)
+ if err != nil {
+ return err
+ }
+ b = enc.indentBuf.Bytes()
+ }
+ if _, err = enc.w.Write(b); err != nil {
enc.err = err
}
encodeStatePool.Put(e)
return err
}
-// RawMessage is a raw encoded JSON object.
+// SetIndent instructs the encoder to format each subsequent encoded
+// value as if indented by the package-level function Indent(dst, src, prefix, indent).
+// Calling SetIndent("", "") disables indentation.
+func (enc *Encoder) SetIndent(prefix, indent string) {
+ enc.indentPrefix = prefix
+ enc.indentValue = indent
+}
+
+// SetEscapeHTML specifies whether problematic HTML characters
+// should be escaped inside JSON quoted strings.
+// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
+// to avoid certain safety problems that can arise when embedding JSON in HTML.
+//
+// In non-HTML settings where the escaping interferes with the readability
+// of the output, SetEscapeHTML(false) disables this behavior.
+func (enc *Encoder) SetEscapeHTML(on bool) {
+ enc.escapeHTML = on
+}
+
+// RawMessage is a raw encoded JSON value.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage []byte
diff --git a/libgo/go/encoding/json/stream_test.go b/libgo/go/encoding/json/stream_test.go
index c2e3040..84edeb1 100644
--- a/libgo/go/encoding/json/stream_test.go
+++ b/libgo/go/encoding/json/stream_test.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -44,6 +44,9 @@ func TestEncoder(t *testing.T) {
for i := 0; i <= len(streamTest); i++ {
var buf bytes.Buffer
enc := NewEncoder(&buf)
+ // Check that enc.SetIndent("", "") turns off indentation.
+ enc.SetIndent(">", ".")
+ enc.SetIndent("", "")
for j, v := range streamTest[0:i] {
if err := enc.Encode(v); err != nil {
t.Fatalf("encode #%d: %v", j, err)
@@ -57,6 +60,69 @@ func TestEncoder(t *testing.T) {
}
}
+var streamEncodedIndent = `0.1
+"hello"
+null
+true
+false
+[
+>."a",
+>."b",
+>."c"
+>]
+{
+>."ß": "long s",
+>."K": "Kelvin"
+>}
+3.14
+`
+
+func TestEncoderIndent(t *testing.T) {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ enc.SetIndent(">", ".")
+ for _, v := range streamTest {
+ enc.Encode(v)
+ }
+ if have, want := buf.String(), streamEncodedIndent; have != want {
+ t.Error("indented encoding mismatch")
+ diff(t, []byte(have), []byte(want))
+ }
+}
+
+func TestEncoderSetEscapeHTML(t *testing.T) {
+ var c C
+ var ct CText
+ for _, tt := range []struct {
+ name string
+ v interface{}
+ wantEscape string
+ want string
+ }{
+ {"c", c, `"\u003c\u0026\u003e"`, `"<&>"`},
+ {"ct", ct, `"\"\u003c\u0026\u003e\""`, `"\"<&>\""`},
+ {`"<&>"`, "<&>", `"\u003c\u0026\u003e"`, `"<&>"`},
+ } {
+ var buf bytes.Buffer
+ enc := NewEncoder(&buf)
+ if err := enc.Encode(tt.v); err != nil {
+ t.Fatalf("Encode(%s): %s", tt.name, err)
+ }
+ if got := strings.TrimSpace(buf.String()); got != tt.wantEscape {
+ t.Errorf("Encode(%s) = %#q, want %#q", tt.name, got, tt.wantEscape)
+ }
+ buf.Reset()
+ enc.SetEscapeHTML(false)
+ if err := enc.Encode(tt.v); err != nil {
+ t.Fatalf("SetEscapeHTML(false) Encode(%s): %s", tt.name, err)
+ }
+ if got := strings.TrimSpace(buf.String()); got != tt.want {
+ t.Errorf("SetEscapeHTML(false) Encode(%s) = %#q, want %#q",
+ tt.name, got, tt.want)
+ }
+ }
+}
+
func TestDecoder(t *testing.T) {
for i := 0; i <= len(streamTest); i++ {
// Use stream without newlines as input,
diff --git a/libgo/go/encoding/json/tagkey_test.go b/libgo/go/encoding/json/tagkey_test.go
index 85bb4ba..c1739ea 100644
--- a/libgo/go/encoding/json/tagkey_test.go
+++ b/libgo/go/encoding/json/tagkey_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/json/tags_test.go b/libgo/go/encoding/json/tags_test.go
index 91fb188..8ba8ddd 100644
--- a/libgo/go/encoding/json/tags_test.go
+++ b/libgo/go/encoding/json/tags_test.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/pem/pem.go b/libgo/go/encoding/pem/pem.go
index 506196b..ff2bed1 100644
--- a/libgo/go/encoding/pem/pem.go
+++ b/libgo/go/encoding/pem/pem.go
@@ -150,7 +150,7 @@ func Decode(data []byte) (p *Block, rest []byte) {
func decodeError(data, rest []byte) (*Block, []byte) {
// If we get here then we have rejected a likely looking, but
// ultimately invalid PEM block. We need to start over from a new
- // position. We have consumed the preamble line and will have consumed
+ // position. We have consumed the preamble line and will have consumed
// any lines which could be header lines. However, a valid preamble
// line is not a valid header line, therefore we cannot have consumed
// the preamble line for the any subsequent block. Thus, we will always
diff --git a/libgo/go/encoding/xml/marshal.go b/libgo/go/encoding/xml/marshal.go
index 8ebd693..abb078c 100644
--- a/libgo/go/encoding/xml/marshal.go
+++ b/libgo/go/encoding/xml/marshal.go
@@ -26,14 +26,14 @@ const (
//
// Marshal handles an array or slice by marshalling each of the elements.
// Marshal handles a pointer by marshalling the value it points at or, if the
-// pointer is nil, by writing nothing. Marshal handles an interface value by
+// pointer is nil, by writing nothing. Marshal handles an interface value by
// marshalling the value it contains or, if the interface value is nil, by
-// writing nothing. Marshal handles all other data by writing one or more XML
+// writing nothing. Marshal handles all other data by writing one or more XML
// elements containing the data.
//
// The name for the XML elements is taken from, in order of preference:
// - the tag on the XMLName field, if the data is a struct
-// - the value of the XMLName field of type xml.Name
+// - the value of the XMLName field of type Name
// - the tag of the struct field used to obtain the data
// - the name of the struct field used to obtain the data
// - the name of the marshalled type
@@ -63,7 +63,7 @@ const (
// value were part of the outer struct.
//
// If a field uses a tag "a>b>c", then the element c will be nested inside
-// parent elements a and b. Fields that appear next to each other that name
+// parent elements a and b. Fields that appear next to each other that name
// the same parent will be enclosed in one XML element.
//
// See MarshalIndent for an example.
@@ -175,10 +175,9 @@ func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error {
}
var (
- begComment = []byte("<!--")
- endComment = []byte("-->")
- endProcInst = []byte("?>")
- endDirective = []byte(">")
+ begComment = []byte("<!--")
+ endComment = []byte("-->")
+ endProcInst = []byte("?>")
)
// EncodeToken writes the given XML token to the stream.
@@ -217,7 +216,7 @@ func (enc *Encoder) EncodeToken(t Token) error {
return p.cachedWriteError()
case ProcInst:
// First token to be encoded which is also a ProcInst with target of xml
- // is the xml declaration. The only ProcInst where target of xml is allowed.
+ // is the xml declaration. The only ProcInst where target of xml is allowed.
if t.Target == "xml" && p.Buffered() != 0 {
return fmt.Errorf("xml: EncodeToken of ProcInst xml target only valid for xml declaration, first token encoded")
}
@@ -850,14 +849,14 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
switch k {
case reflect.String:
s := vf.String()
- dashDash = strings.Index(s, "--") >= 0
+ dashDash = strings.Contains(s, "--")
dashLast = s[len(s)-1] == '-'
if !dashDash {
p.WriteString(s)
}
case reflect.Slice:
b := vf.Bytes()
- dashDash = bytes.Index(b, ddBytes) >= 0
+ dashDash = bytes.Contains(b, ddBytes)
dashLast = b[len(b)-1] == '-'
if !dashDash {
p.Write(b)
@@ -949,8 +948,8 @@ type parentStack struct {
}
// trim updates the XML context to match the longest common prefix of the stack
-// and the given parents. A closing tag will be written for every parent
-// popped. Passing a zero slice or nil will close all the elements.
+// and the given parents. A closing tag will be written for every parent
+// popped. Passing a zero slice or nil will close all the elements.
func (s *parentStack) trim(parents []string) error {
split := 0
for ; split < len(parents) && split < len(s.stack); split++ {
diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go
index 77b4c7b..937432e 100644
--- a/libgo/go/encoding/xml/read.go
+++ b/libgo/go/encoding/xml/read.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -27,7 +27,7 @@ import (
// discarded.
//
// Because Unmarshal uses the reflect package, it can only assign
-// to exported (upper case) fields. Unmarshal uses a case-sensitive
+// to exported (upper case) fields. Unmarshal uses a case-sensitive
// comparison to match XML element names to tag values and struct
// field names.
//
@@ -37,9 +37,9 @@ import (
//
// * If the struct has a field of type []byte or string with tag
// ",innerxml", Unmarshal accumulates the raw XML nested inside the
-// element in that field. The rest of the rules still apply.
+// element in that field. The rest of the rules still apply.
//
-// * If the struct has a field named XMLName of type xml.Name,
+// * If the struct has a field named XMLName of type Name,
// Unmarshal records the element name in that field.
//
// * If the XMLName field has an associated tag of the form
@@ -59,7 +59,7 @@ import (
//
// * If the XML element contains comments, they are accumulated in
// the first struct field that has tag ",comment". The struct
-// field may have type []byte or string. If there is no such
+// field may have type []byte or string. If there is no such
// field, the comments are discarded.
//
// * If the XML element contains a sub-element whose name matches
@@ -102,11 +102,11 @@ import (
//
// Unmarshal maps an XML element or attribute value to an integer or
// floating-point field by setting the field to the result of
-// interpreting the string value in decimal. There is no check for
+// interpreting the string value in decimal. There is no check for
// overflow.
//
-// Unmarshal maps an XML element to an xml.Name by recording the
-// element name.
+// Unmarshal maps an XML element to a Name by recording the element
+// name.
//
// Unmarshal maps an XML element to a pointer by setting the pointer
// to a freshly allocated value and then mapping the element to that value.
@@ -115,13 +115,13 @@ func Unmarshal(data []byte, v interface{}) error {
return NewDecoder(bytes.NewReader(data)).Decode(v)
}
-// Decode works like xml.Unmarshal, except it reads the decoder
+// Decode works like Unmarshal, except it reads the decoder
// stream to find the start element.
func (d *Decoder) Decode(v interface{}) error {
return d.DecodeElement(v, nil)
}
-// DecodeElement works like xml.Unmarshal except that it takes
+// DecodeElement works like Unmarshal except that it takes
// a pointer to the start XML element to decode into v.
// It is useful when a client reads some raw XML tokens itself
// but also wants to defer to Unmarshal for some elements.
diff --git a/libgo/go/encoding/xml/typeinfo.go b/libgo/go/encoding/xml/typeinfo.go
index 6483c8d..70da962 100644
--- a/libgo/go/encoding/xml/typeinfo.go
+++ b/libgo/go/encoding/xml/typeinfo.go
@@ -1,4 +1,4 @@
-// Copyright 2011 The Go Authors. All rights reserved.
+// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/libgo/go/encoding/xml/xml.go b/libgo/go/encoding/xml/xml.go
index 45f4157..9a3b792 100644
--- a/libgo/go/encoding/xml/xml.go
+++ b/libgo/go/encoding/xml/xml.go
@@ -219,7 +219,7 @@ func NewDecoder(r io.Reader) *Decoder {
//
// Slices of bytes in the returned token data refer to the
// parser's internal buffer and remain valid only until the next
-// call to Token. To acquire a copy of the bytes, call CopyToken
+// call to Token. To acquire a copy of the bytes, call CopyToken
// or the token's Copy method.
//
// Token expands self-closing elements such as <br/>
@@ -237,10 +237,11 @@ func NewDecoder(r io.Reader) *Decoder {
// set to the URL identifying its name space when known.
// If Token encounters an unrecognized name space prefix,
// it uses the prefix as the Space rather than report an error.
-func (d *Decoder) Token() (t Token, err error) {
+func (d *Decoder) Token() (Token, error) {
+ var t Token
+ var err error
if d.stk != nil && d.stk.kind == stkEOF {
- err = io.EOF
- return
+ return nil, io.EOF
}
if d.nextToken != nil {
t = d.nextToken
@@ -249,7 +250,7 @@ func (d *Decoder) Token() (t Token, err error) {
if err == io.EOF && d.stk != nil && d.stk.kind != stkEOF {
err = d.syntaxError("unexpected EOF")
}
- return
+ return t, err
}
if !d.Strict {
@@ -292,7 +293,7 @@ func (d *Decoder) Token() (t Token, err error) {
}
t = t1
}
- return
+ return t, err
}
const xmlURL = "http://www.w3.org/XML/1998/namespace"
@@ -331,7 +332,7 @@ func (d *Decoder) switchToReader(r io.Reader) {
}
// Parsing state - stack holds old name space translations
-// and the current set of open elements. The translations to pop when
+// and the current set of open elements. The translations to pop when
// ending a given tag are *below* it on the stack, which is
// more work but forced on us by XML.
type stack struct {
@@ -1229,7 +1230,7 @@ func isNameString(s string) bool {
// These tables were generated by cut and paste from Appendix B of
// the XML spec at http://www.xml.com/axml/testaxml.htm
-// and then reformatting. First corresponds to (Letter | '_' | ':')
+// and then reformatting. First corresponds to (Letter | '_' | ':')
// and second corresponds to NameChar.
var first = &unicode.RangeTable{
diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go
index 5d5e4bf..dad6ed9 100644
--- a/libgo/go/encoding/xml/xml_test.go
+++ b/libgo/go/encoding/xml/xml_test.go
@@ -1,4 +1,4 @@
-// Copyright 2009 The Go Authors. All rights reserved.
+// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -184,8 +184,6 @@ const nonStrictInput = `
<tag>&0a;</tag>
`
-var nonStringEntity = map[string]string{"": "oops!", "0a": "oops!"}
-
var nonStrictTokens = []Token{
CharData("\n"),
StartElement{Name{"", "tag"}, []Attr{}},
@@ -652,10 +650,6 @@ func TestDisallowedCharacters(t *testing.T) {
}
}
-type procInstEncodingTest struct {
- expect, got string
-}
-
var procInstTests = []struct {
input string
expect [2]string