aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/encoding
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-12-12 23:40:51 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-12-12 23:40:51 +0000
commitab61e9c4da707f3bc7b177c0c8f92daccdb142dc (patch)
tree0c68629fac9d7c6f103b401c9063ef00ed259f06 /libgo/go/encoding
parent6e456f4cf4deee3e2ccd9849286f59b90644c48b (diff)
downloadgcc-ab61e9c4da707f3bc7b177c0c8f92daccdb142dc.zip
gcc-ab61e9c4da707f3bc7b177c0c8f92daccdb142dc.tar.gz
gcc-ab61e9c4da707f3bc7b177c0c8f92daccdb142dc.tar.bz2
libgo: Update to weekly.2011-11-18.
From-SVN: r182266
Diffstat (limited to 'libgo/go/encoding')
-rw-r--r--libgo/go/encoding/json/bench_test.go157
-rw-r--r--libgo/go/encoding/json/decode.go6
-rw-r--r--libgo/go/encoding/json/scanner.go19
-rw-r--r--libgo/go/encoding/json/scanner_test.go5
-rw-r--r--libgo/go/encoding/xml/xml_test.go17
5 files changed, 188 insertions, 16 deletions
diff --git a/libgo/go/encoding/json/bench_test.go b/libgo/go/encoding/json/bench_test.go
new file mode 100644
index 0000000..f0c5201
--- /dev/null
+++ b/libgo/go/encoding/json/bench_test.go
@@ -0,0 +1,157 @@
+// 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.
+
+// Large data benchmark.
+// The JSON data is a summary of agl's changes in the
+// go, webkit, and chromium open source projects.
+// We benchmark converting between the JSON form
+// and in-memory data structures.
+
+package json
+
+import (
+ "bytes"
+ "compress/gzip"
+ "io/ioutil"
+ "os"
+ "testing"
+)
+
+type codeResponse struct {
+ Tree *codeNode `json:"tree"`
+ Username string `json:"username"`
+}
+
+type codeNode struct {
+ Name string `json:"name"`
+ Kids []*codeNode `json:"kids"`
+ CLWeight float64 `json:"cl_weight"`
+ Touches int `json:"touches"`
+ MinT int64 `json:"min_t"`
+ MaxT int64 `json:"max_t"`
+ MeanT int64 `json:"mean_t"`
+}
+
+var codeJSON []byte
+var codeStruct codeResponse
+
+func codeInit() {
+ f, err := os.Open("testdata/code.json.gz")
+ if err != nil {
+ panic(err)
+ }
+ defer f.Close()
+ gz, err := gzip.NewReader(f)
+ if err != nil {
+ panic(err)
+ }
+ data, err := ioutil.ReadAll(gz)
+ if err != nil {
+ panic(err)
+ }
+
+ codeJSON = data
+
+ if err := Unmarshal(codeJSON, &codeStruct); err != nil {
+ panic("unmarshal code.json: " + err.Error())
+ }
+
+ if data, err = Marshal(&codeStruct); err != nil {
+ panic("marshal code.json: " + err.Error())
+ }
+
+ if !bytes.Equal(data, codeJSON) {
+ println("different lengths", len(data), len(codeJSON))
+ for i := 0; i < len(data) && i < len(codeJSON); i++ {
+ if data[i] != codeJSON[i] {
+ println("re-marshal: changed at byte", i)
+ println("orig: ", string(codeJSON[i-10:i+10]))
+ println("new: ", string(data[i-10:i+10]))
+ break
+ }
+ }
+ panic("re-marshal code.json: different result")
+ }
+}
+
+func BenchmarkCodeEncoder(b *testing.B) {
+ if codeJSON == nil {
+ b.StopTimer()
+ codeInit()
+ b.StartTimer()
+ }
+ enc := NewEncoder(ioutil.Discard)
+ for i := 0; i < b.N; i++ {
+ if err := enc.Encode(&codeStruct); err != nil {
+ panic(err)
+ }
+ }
+ b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeMarshal(b *testing.B) {
+ if codeJSON == nil {
+ b.StopTimer()
+ codeInit()
+ b.StartTimer()
+ }
+ for i := 0; i < b.N; i++ {
+ if _, err := Marshal(&codeStruct); err != nil {
+ panic(err)
+ }
+ }
+ b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeDecoder(b *testing.B) {
+ if codeJSON == nil {
+ b.StopTimer()
+ codeInit()
+ b.StartTimer()
+ }
+ var buf bytes.Buffer
+ dec := NewDecoder(&buf)
+ var r codeResponse
+ for i := 0; i < b.N; i++ {
+ buf.Write(codeJSON)
+ // hide EOF
+ buf.WriteByte('\n')
+ buf.WriteByte('\n')
+ buf.WriteByte('\n')
+ if err := dec.Decode(&r); err != nil {
+ panic(err)
+ }
+ }
+ b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeUnmarshal(b *testing.B) {
+ if codeJSON == nil {
+ b.StopTimer()
+ codeInit()
+ b.StartTimer()
+ }
+ for i := 0; i < b.N; i++ {
+ var r codeResponse
+ if err := Unmarshal(codeJSON, &r); err != nil {
+ panic(err)
+ }
+ }
+ b.SetBytes(int64(len(codeJSON)))
+}
+
+func BenchmarkCodeUnmarshalReuse(b *testing.B) {
+ if codeJSON == nil {
+ b.StopTimer()
+ codeInit()
+ b.StartTimer()
+ }
+ var r codeResponse
+ for i := 0; i < b.N; i++ {
+ if err := Unmarshal(codeJSON, &r); err != nil {
+ panic(err)
+ }
+ }
+ b.SetBytes(int64(len(codeJSON)))
+}
diff --git a/libgo/go/encoding/json/decode.go b/libgo/go/encoding/json/decode.go
index 41295d2..2ea06c5 100644
--- a/libgo/go/encoding/json/decode.go
+++ b/libgo/go/encoding/json/decode.go
@@ -227,7 +227,7 @@ func (d *decodeState) value(v reflect.Value) {
// d.scan thinks we're still at the beginning of the item.
// Feed in an empty string - the shortest, simplest value -
// so that it knows we got to the end of the value.
- if d.scan.step == stateRedo {
+ if d.scan.redo {
panic("redo")
}
d.scan.step(&d.scan, '"')
@@ -381,6 +381,7 @@ func (d *decodeState) array(v reflect.Value) {
d.error(errPhase)
}
}
+
if i < av.Len() {
if !sv.IsValid() {
// Array. Zero the rest.
@@ -392,6 +393,9 @@ func (d *decodeState) array(v reflect.Value) {
sv.SetLen(i)
}
}
+ if i == 0 && av.Kind() == reflect.Slice && sv.IsNil() {
+ sv.Set(reflect.MakeSlice(sv.Type(), 0, 0))
+ }
}
// object consumes an object from d.data[d.off-1:], decoding into the value v.
diff --git a/libgo/go/encoding/json/scanner.go b/libgo/go/encoding/json/scanner.go
index 1796904..2661f41 100644
--- a/libgo/go/encoding/json/scanner.go
+++ b/libgo/go/encoding/json/scanner.go
@@ -80,6 +80,9 @@ type scanner struct {
// on a 64-bit Mac Mini, and it's nicer to read.
step func(*scanner, int) int
+ // Reached end of top-level value.
+ endTop bool
+
// Stack of what we're in the middle of - array values, object keys, object values.
parseState []int
@@ -87,6 +90,7 @@ type scanner struct {
err error
// 1-byte redo (see undo method)
+ redo bool
redoCode int
redoState func(*scanner, int) int
@@ -135,6 +139,8 @@ func (s *scanner) reset() {
s.step = stateBeginValue
s.parseState = s.parseState[0:0]
s.err = nil
+ s.redo = false
+ s.endTop = false
}
// eof tells the scanner that the end of input has been reached.
@@ -143,11 +149,11 @@ func (s *scanner) eof() int {
if s.err != nil {
return scanError
}
- if s.step == stateEndTop {
+ if s.endTop {
return scanEnd
}
s.step(s, ' ')
- if s.step == stateEndTop {
+ if s.endTop {
return scanEnd
}
if s.err == nil {
@@ -166,8 +172,10 @@ func (s *scanner) pushParseState(p int) {
func (s *scanner) popParseState() {
n := len(s.parseState) - 1
s.parseState = s.parseState[0:n]
+ s.redo = false
if n == 0 {
s.step = stateEndTop
+ s.endTop = true
} else {
s.step = stateEndValue
}
@@ -269,6 +277,7 @@ func stateEndValue(s *scanner, c int) int {
if n == 0 {
// Completed top-level before the current byte.
s.step = stateEndTop
+ s.endTop = true
return stateEndTop(s, c)
}
if c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
@@ -606,16 +615,18 @@ func quoteChar(c int) string {
// undo causes the scanner to return scanCode from the next state transition.
// This gives callers a simple 1-byte undo mechanism.
func (s *scanner) undo(scanCode int) {
- if s.step == stateRedo {
- panic("invalid use of scanner")
+ if s.redo {
+ panic("json: invalid use of scanner")
}
s.redoCode = scanCode
s.redoState = s.step
s.step = stateRedo
+ s.redo = true
}
// stateRedo helps implement the scanner's 1-byte undo.
func stateRedo(s *scanner, c int) int {
+ s.redo = false
s.step = s.redoState
return s.redoCode
}
diff --git a/libgo/go/encoding/json/scanner_test.go b/libgo/go/encoding/json/scanner_test.go
index a0a5995..14d8508 100644
--- a/libgo/go/encoding/json/scanner_test.go
+++ b/libgo/go/encoding/json/scanner_test.go
@@ -186,11 +186,12 @@ func TestNextValueBig(t *testing.T) {
}
}
+var benchScan scanner
+
func BenchmarkSkipValue(b *testing.B) {
initBig()
- var scan scanner
for i := 0; i < b.N; i++ {
- nextValue(jsonBig, &scan)
+ nextValue(jsonBig, &benchScan)
}
b.SetBytes(int64(len(jsonBig)))
}
diff --git a/libgo/go/encoding/xml/xml_test.go b/libgo/go/encoding/xml/xml_test.go
index 6c874fa..bcb22af 100644
--- a/libgo/go/encoding/xml/xml_test.go
+++ b/libgo/go/encoding/xml/xml_test.go
@@ -7,7 +7,6 @@ package xml
import (
"bytes"
"io"
- "os"
"reflect"
"strings"
"testing"
@@ -43,17 +42,17 @@ var rawTokens = []Token{
CharData([]byte("World <>'\" 白鵬翔")),
EndElement{Name{"", "hello"}},
CharData([]byte("\n ")),
- StartElement{Name{"", "goodbye"}, nil},
+ StartElement{Name{"", "goodbye"}, []Attr{}},
EndElement{Name{"", "goodbye"}},
CharData([]byte("\n ")),
StartElement{Name{"", "outer"}, []Attr{{Name{"foo", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
CharData([]byte("\n ")),
- StartElement{Name{"", "inner"}, nil},
+ StartElement{Name{"", "inner"}, []Attr{}},
EndElement{Name{"", "inner"}},
CharData([]byte("\n ")),
EndElement{Name{"", "outer"}},
CharData([]byte("\n ")),
- StartElement{Name{"tag", "name"}, nil},
+ StartElement{Name{"tag", "name"}, []Attr{}},
CharData([]byte("\n ")),
CharData([]byte("Some text here.")),
CharData([]byte("\n ")),
@@ -77,17 +76,17 @@ var cookedTokens = []Token{
CharData([]byte("World <>'\" 白鵬翔")),
EndElement{Name{"ns2", "hello"}},
CharData([]byte("\n ")),
- StartElement{Name{"ns2", "goodbye"}, nil},
+ StartElement{Name{"ns2", "goodbye"}, []Attr{}},
EndElement{Name{"ns2", "goodbye"}},
CharData([]byte("\n ")),
StartElement{Name{"ns2", "outer"}, []Attr{{Name{"ns1", "attr"}, "value"}, {Name{"xmlns", "tag"}, "ns4"}}},
CharData([]byte("\n ")),
- StartElement{Name{"ns2", "inner"}, nil},
+ StartElement{Name{"ns2", "inner"}, []Attr{}},
EndElement{Name{"ns2", "inner"}},
CharData([]byte("\n ")),
EndElement{Name{"ns2", "outer"}},
CharData([]byte("\n ")),
- StartElement{Name{"ns3", "name"}, nil},
+ StartElement{Name{"ns3", "name"}, []Attr{}},
CharData([]byte("\n ")),
CharData([]byte("Some text here.")),
CharData([]byte("\n ")),
@@ -105,7 +104,7 @@ var rawTokensAltEncoding = []Token{
CharData([]byte("\n")),
ProcInst{"xml", []byte(`version="1.0" encoding="x-testing-uppercase"`)},
CharData([]byte("\n")),
- StartElement{Name{"", "tag"}, nil},
+ StartElement{Name{"", "tag"}, []Attr{}},
CharData([]byte("value")),
EndElement{Name{"", "tag"}},
}
@@ -205,7 +204,7 @@ func (d *downCaser) ReadByte() (c byte, err error) {
func (d *downCaser) Read(p []byte) (int, error) {
d.t.Fatalf("unexpected Read call on downCaser reader")
- return 0, os.EINVAL
+ panic("unreachable")
}
func TestRawTokenAltEncoding(t *testing.T) {