1
2
3
4
5
6
7
8
9 package fmtsort
10
11 import (
12 "cmp"
13 "reflect"
14 "slices"
15 )
16
17
18
19
20
21
22
23
24 type SortedMap []KeyValue
25
26
27 type KeyValue struct {
28 Key, Value reflect.Value
29 }
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 func Sort(mapValue reflect.Value) SortedMap {
50 if mapValue.Type().Kind() != reflect.Map {
51 return nil
52 }
53
54
55
56 n := mapValue.Len()
57 sorted := make(SortedMap, 0, n)
58 iter := mapValue.MapRange()
59 for iter.Next() {
60 sorted = append(sorted, KeyValue{iter.Key(), iter.Value()})
61 }
62 slices.SortStableFunc(sorted, func(a, b KeyValue) int {
63 return compare(a.Key, b.Key)
64 })
65 return sorted
66 }
67
68
69
70
71
72 func compare(aVal, bVal reflect.Value) int {
73 aType, bType := aVal.Type(), bVal.Type()
74 if aType != bType {
75 return -1
76 }
77 switch aVal.Kind() {
78 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
79 return cmp.Compare(aVal.Int(), bVal.Int())
80 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
81 return cmp.Compare(aVal.Uint(), bVal.Uint())
82 case reflect.String:
83 return cmp.Compare(aVal.String(), bVal.String())
84 case reflect.Float32, reflect.Float64:
85 return cmp.Compare(aVal.Float(), bVal.Float())
86 case reflect.Complex64, reflect.Complex128:
87 a, b := aVal.Complex(), bVal.Complex()
88 if c := cmp.Compare(real(a), real(b)); c != 0 {
89 return c
90 }
91 return cmp.Compare(imag(a), imag(b))
92 case reflect.Bool:
93 a, b := aVal.Bool(), bVal.Bool()
94 switch {
95 case a == b:
96 return 0
97 case a:
98 return 1
99 default:
100 return -1
101 }
102 case reflect.Pointer, reflect.UnsafePointer:
103 return cmp.Compare(aVal.Pointer(), bVal.Pointer())
104 case reflect.Chan:
105 if c, ok := nilCompare(aVal, bVal); ok {
106 return c
107 }
108 return cmp.Compare(aVal.Pointer(), bVal.Pointer())
109 case reflect.Struct:
110 for i := 0; i < aVal.NumField(); i++ {
111 if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 {
112 return c
113 }
114 }
115 return 0
116 case reflect.Array:
117 for i := 0; i < aVal.Len(); i++ {
118 if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 {
119 return c
120 }
121 }
122 return 0
123 case reflect.Interface:
124 if c, ok := nilCompare(aVal, bVal); ok {
125 return c
126 }
127 c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type()))
128 if c != 0 {
129 return c
130 }
131 return compare(aVal.Elem(), bVal.Elem())
132 default:
133
134 panic("bad type in compare: " + aType.String())
135 }
136 }
137
138
139
140
141
142
143 func nilCompare(aVal, bVal reflect.Value) (int, bool) {
144 if aVal.IsNil() {
145 if bVal.IsNil() {
146 return 0, true
147 }
148 return -1, true
149 }
150 if bVal.IsNil() {
151 return 1, true
152 }
153 return 0, false
154 }
155
View as plain text