Source file src/internal/fmtsort/sort.go
1
2
3
4
5
6
7
8
9 package fmtsort
10
11 import (
12 "reflect"
13 "sort"
14 )
15
16
17
18
19
20
21 type SortedMap struct {
22 Key []reflect.Value
23 Value []reflect.Value
24 }
25
26 func (o *SortedMap) Len() int { return len(o.Key) }
27 func (o *SortedMap) Less(i, j int) bool { return compare(o.Key[i], o.Key[j]) < 0 }
28 func (o *SortedMap) Swap(i, j int) {
29 o.Key[i], o.Key[j] = o.Key[j], o.Key[i]
30 o.Value[i], o.Value[j] = o.Value[j], o.Value[i]
31 }
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 func Sort(mapValue reflect.Value) *SortedMap {
53 if mapValue.Type().Kind() != reflect.Map {
54 return nil
55 }
56 key := make([]reflect.Value, mapValue.Len())
57 value := make([]reflect.Value, len(key))
58 iter := mapValue.MapRange()
59 for i := 0; iter.Next(); i++ {
60 key[i] = iter.Key()
61 value[i] = iter.Value()
62 }
63 sorted := &SortedMap{
64 Key: key,
65 Value: value,
66 }
67 sort.Stable(sorted)
68 return sorted
69 }
70
71
72
73
74
75 func compare(aVal, bVal reflect.Value) int {
76 aType, bType := aVal.Type(), bVal.Type()
77 if aType != bType {
78 return -1
79 }
80 switch aVal.Kind() {
81 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
82 a, b := aVal.Int(), bVal.Int()
83 switch {
84 case a < b:
85 return -1
86 case a > b:
87 return 1
88 default:
89 return 0
90 }
91 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
92 a, b := aVal.Uint(), bVal.Uint()
93 switch {
94 case a < b:
95 return -1
96 case a > b:
97 return 1
98 default:
99 return 0
100 }
101 case reflect.String:
102 a, b := aVal.String(), bVal.String()
103 switch {
104 case a < b:
105 return -1
106 case a > b:
107 return 1
108 default:
109 return 0
110 }
111 case reflect.Float32, reflect.Float64:
112 return floatCompare(aVal.Float(), bVal.Float())
113 case reflect.Complex64, reflect.Complex128:
114 a, b := aVal.Complex(), bVal.Complex()
115 if c := floatCompare(real(a), real(b)); c != 0 {
116 return c
117 }
118 return floatCompare(imag(a), imag(b))
119 case reflect.Bool:
120 a, b := aVal.Bool(), bVal.Bool()
121 switch {
122 case a == b:
123 return 0
124 case a:
125 return 1
126 default:
127 return -1
128 }
129 case reflect.Ptr:
130 a, b := aVal.Pointer(), bVal.Pointer()
131 switch {
132 case a < b:
133 return -1
134 case a > b:
135 return 1
136 default:
137 return 0
138 }
139 case reflect.Chan:
140 if c, ok := nilCompare(aVal, bVal); ok {
141 return c
142 }
143 ap, bp := aVal.Pointer(), bVal.Pointer()
144 switch {
145 case ap < bp:
146 return -1
147 case ap > bp:
148 return 1
149 default:
150 return 0
151 }
152 case reflect.Struct:
153 for i := 0; i < aVal.NumField(); i++ {
154 if c := compare(aVal.Field(i), bVal.Field(i)); c != 0 {
155 return c
156 }
157 }
158 return 0
159 case reflect.Array:
160 for i := 0; i < aVal.Len(); i++ {
161 if c := compare(aVal.Index(i), bVal.Index(i)); c != 0 {
162 return c
163 }
164 }
165 return 0
166 case reflect.Interface:
167 if c, ok := nilCompare(aVal, bVal); ok {
168 return c
169 }
170 c := compare(reflect.ValueOf(aVal.Elem().Type()), reflect.ValueOf(bVal.Elem().Type()))
171 if c != 0 {
172 return c
173 }
174 return compare(aVal.Elem(), bVal.Elem())
175 default:
176
177 panic("bad type in compare: " + aType.String())
178 }
179 }
180
181
182
183
184
185
186 func nilCompare(aVal, bVal reflect.Value) (int, bool) {
187 if aVal.IsNil() {
188 if bVal.IsNil() {
189 return 0, true
190 }
191 return -1, true
192 }
193 if bVal.IsNil() {
194 return 1, true
195 }
196 return 0, false
197 }
198
199
200 func floatCompare(a, b float64) int {
201 switch {
202 case isNaN(a):
203 return -1
204 case isNaN(b):
205 return 1
206 case a < b:
207 return -1
208 case a > b:
209 return 1
210 }
211 return 0
212 }
213
214 func isNaN(a float64) bool {
215 return a != a
216 }
217
View as plain text