diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-01-25 20:56:26 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-01-25 20:56:26 +0000 |
commit | df1304ee03f41aed179545d1e8b4684cfd22bbdf (patch) | |
tree | c68d6b2a9f5b82a23171b0a488a4b7e5c63ad860 /libgo/go/text | |
parent | 3be18e47c33b61365786831e0f967f42b09922c9 (diff) | |
download | gcc-df1304ee03f41aed179545d1e8b4684cfd22bbdf.zip gcc-df1304ee03f41aed179545d1e8b4684cfd22bbdf.tar.gz gcc-df1304ee03f41aed179545d1e8b4684cfd22bbdf.tar.bz2 |
libgo: Update to weekly.2012-01-15.
From-SVN: r183539
Diffstat (limited to 'libgo/go/text')
-rw-r--r-- | libgo/go/text/template/doc.go | 4 | ||||
-rw-r--r-- | libgo/go/text/template/exec.go | 52 | ||||
-rw-r--r-- | libgo/go/text/template/exec_test.go | 17 |
3 files changed, 54 insertions, 19 deletions
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go index 4208d53..3be1ec4 100644 --- a/libgo/go/text/template/doc.go +++ b/libgo/go/text/template/doc.go @@ -50,7 +50,9 @@ data, defined in detail below. The value of the pipeline must be an array, slice, or map. If the value of the pipeline has length zero, nothing is output; otherwise, dot is set to the successive elements of the array, - slice, or map and T1 is executed. + slice, or map and T1 is executed. If the value is a map and the + keys are of basic type with a defined order ("comparable"), the + elements will be visited in sorted key order. {{range pipeline}} T1 {{else}} T0 {{end}} The value of the pipeline must be an array, slice, or map. If diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go index acb88af..973189a 100644 --- a/libgo/go/text/template/exec.go +++ b/libgo/go/text/template/exec.go @@ -9,6 +9,7 @@ import ( "io" "reflect" "runtime" + "sort" "strings" "text/template/parse" ) @@ -78,10 +79,14 @@ func (s *state) error(err error) { func errRecover(errp *error) { e := recover() if e != nil { - if _, ok := e.(runtime.Error); ok { + switch err := e.(type) { + case runtime.Error: + panic(e) + case error: + *errp = err + default: panic(e) } - *errp = e.(error) } } @@ -230,7 +235,7 @@ func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { if val.Len() == 0 { break } - for _, key := range val.MapKeys() { + for _, key := range sortKeys(val.MapKeys()) { oneIteration(key, val.MapIndex(key)) } return @@ -672,3 +677,44 @@ func (s *state) printValue(n parse.Node, v reflect.Value) { } fmt.Fprint(s.wr, v.Interface()) } + +// Types to help sort the keys in a map for reproducible output. + +type rvs []reflect.Value + +func (x rvs) Len() int { return len(x) } +func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +type rvInts struct{ rvs } + +func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() } + +type rvUints struct{ rvs } + +func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() } + +type rvFloats struct{ rvs } + +func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() } + +type rvStrings struct{ rvs } + +func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() } + +// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys. +func sortKeys(v []reflect.Value) []reflect.Value { + if len(v) <= 1 { + return v + } + switch v[0].Kind() { + case reflect.Float32, reflect.Float64: + sort.Sort(rvFloats{v}) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + sort.Sort(rvInts{v}) + case reflect.String: + sort.Sort(rvStrings{v}) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + sort.Sort(rvUints{v}) + } + return v +} diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go index e33988b..2070cef 100644 --- a/libgo/go/text/template/exec_test.go +++ b/libgo/go/text/template/exec_test.go @@ -11,7 +11,6 @@ import ( "fmt" "os" "reflect" - "sort" "strings" "testing" ) @@ -169,18 +168,6 @@ func (t *T) MAdd(a int, b []int) []int { return v } -// MSort is used to sort map keys for stable output. (Nice trick!) -func (t *T) MSort(m map[string]int) []string { - keys := make([]string, len(m)) - i := 0 - for k := range m { - keys[i] = k - i++ - } - sort.Strings(keys) - return keys -} - // EPERM returns a value and an error according to its argument. func (t *T) EPERM(error bool) (bool, error) { if error { @@ -410,9 +397,9 @@ var execTests = []execTest{ {"range empty else", "{{range .SIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, {"range []bool", "{{range .SB}}-{{.}}-{{end}}", "-true--false-", tVal, true}, {"range []int method", "{{range .SI | .MAdd .I}}-{{.}}-{{end}}", "-20--21--22-", tVal, true}, - {"range map", "{{range .MSI | .MSort}}-{{.}}-{{end}}", "-one--three--two-", tVal, true}, + {"range map", "{{range .MSI}}-{{.}}-{{end}}", "-1--3--2-", tVal, true}, {"range empty map no else", "{{range .MSIEmpty}}-{{.}}-{{end}}", "", tVal, true}, - {"range map else", "{{range .MSI | .MSort}}-{{.}}-{{else}}EMPTY{{end}}", "-one--three--two-", tVal, true}, + {"range map else", "{{range .MSI}}-{{.}}-{{else}}EMPTY{{end}}", "-1--3--2-", tVal, true}, {"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true}, {"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true}, {"range empty nil", "{{range .Empty0}}-{{.}}-{{end}}", "", tVal, true}, |