summaryrefslogtreecommitdiff
path: root/spew/dump.go
diff options
context:
space:
mode:
authorPatrick Mezard <[email protected]>2013-10-27 23:44:49 +0100
committerPatrick Mezard <[email protected]>2013-10-27 23:44:49 +0100
commit1fdf49f1b9ce7ab182b1b38bbc847b9807f66f3a (patch)
tree3bdd47a30426d70c79c8b9c66f16e42a620eff00 /spew/dump.go
parent1fe9f5ca4b46a8247ae5939097f5cfc5d8370729 (diff)
config: add SortKeys option to sort native map keys before display
If ConfigState.SortKeys is true, then dump and format will sort map keys before displaying them. Only native types (bool, ints, uint, uintptr, string) are supported, other slices are left unchanged. The motivation is to have more diffable output, mostly for test purpose.
Diffstat (limited to 'spew/dump.go')
-rw-r--r--spew/dump.go56
1 files changed, 56 insertions, 0 deletions
diff --git a/spew/dump.go b/spew/dump.go
index 216c5b3..c06750d 100644
--- a/spew/dump.go
+++ b/spew/dump.go
@@ -24,6 +24,7 @@ import (
"os"
"reflect"
"regexp"
+ "sort"
"strconv"
"strings"
)
@@ -241,6 +242,58 @@ func (d *dumpState) dumpSlice(v reflect.Value) {
}
}
+type valuesSorter struct {
+ values []reflect.Value
+}
+
+func (s *valuesSorter) Len() int {
+ return len(s.values)
+}
+
+func (s *valuesSorter) Swap(i, j int) {
+ s.values[i], s.values[j] = s.values[j], s.values[i]
+}
+
+func (s *valuesSorter) Less(i, j int) bool {
+ switch s.values[i].Kind() {
+ case reflect.Bool:
+ return !s.values[i].Bool() && s.values[j].Bool()
+ case reflect.Float32, reflect.Float64:
+ return s.values[i].Float() < s.values[j].Float()
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ return s.values[i].Int() < s.values[j].Int()
+ case reflect.String:
+ return s.values[i].String() < s.values[j].String()
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ return s.values[i].Uint() < s.values[j].Uint()
+ case reflect.Uintptr:
+ return s.values[i].UnsafeAddr() < s.values[j].UnsafeAddr()
+ }
+ panic("notimplemented")
+}
+
+// Generic sort function for native types: int, uint, bool, string and uintptr.
+// Other inputs are left unchanged.
+func SortValues(values []reflect.Value) {
+ if len(values) == 0 {
+ return
+ }
+ switch values[0].Kind() {
+ case reflect.Bool:
+ sort.Sort(&valuesSorter{values})
+ case reflect.Float32, reflect.Float64:
+ sort.Sort(&valuesSorter{values})
+ case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
+ sort.Sort(&valuesSorter{values})
+ case reflect.String:
+ sort.Sort(&valuesSorter{values})
+ case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
+ sort.Sort(&valuesSorter{values})
+ case reflect.Uintptr:
+ sort.Sort(&valuesSorter{values})
+ }
+}
+
// dump is the main workhorse for dumping a value. It uses the passed reflect
// value to figure out what kind of object we are dealing with and formats it
// appropriately. It is a recursive function, however circular data structures
@@ -349,6 +402,9 @@ func (d *dumpState) dump(v reflect.Value) {
} else {
numEntries := v.Len()
keys := v.MapKeys()
+ if d.cs.SortKeys {
+ SortValues(keys)
+ }
for i, key := range keys {
d.dump(d.unpackValue(key))
d.w.Write(colonSpaceBytes)