sorter.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package yaml
  2. import (
  3. "reflect"
  4. "unicode"
  5. )
  6. type keyList []reflect.Value
  7. func (l keyList) Len() int { return len(l) }
  8. func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
  9. func (l keyList) Less(i, j int) bool {
  10. a := l[i]
  11. b := l[j]
  12. ak := a.Kind()
  13. bk := b.Kind()
  14. for (ak == reflect.Interface || ak == reflect.Ptr) && !a.IsNil() {
  15. a = a.Elem()
  16. ak = a.Kind()
  17. }
  18. for (bk == reflect.Interface || bk == reflect.Ptr) && !b.IsNil() {
  19. b = b.Elem()
  20. bk = b.Kind()
  21. }
  22. af, aok := keyFloat(a)
  23. bf, bok := keyFloat(b)
  24. if aok && bok {
  25. if af != bf {
  26. return af < bf
  27. }
  28. if ak != bk {
  29. return ak < bk
  30. }
  31. return numLess(a, b)
  32. }
  33. if ak != reflect.String || bk != reflect.String {
  34. return ak < bk
  35. }
  36. ar, br := []rune(a.String()), []rune(b.String())
  37. for i := 0; i < len(ar) && i < len(br); i++ {
  38. if ar[i] == br[i] {
  39. continue
  40. }
  41. al := unicode.IsLetter(ar[i])
  42. bl := unicode.IsLetter(br[i])
  43. if al && bl {
  44. return ar[i] < br[i]
  45. }
  46. if al || bl {
  47. return bl
  48. }
  49. var ai, bi int
  50. var an, bn int64
  51. for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
  52. an = an*10 + int64(ar[ai]-'0')
  53. }
  54. for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
  55. bn = bn*10 + int64(br[bi]-'0')
  56. }
  57. if an != bn {
  58. return an < bn
  59. }
  60. if ai != bi {
  61. return ai < bi
  62. }
  63. return ar[i] < br[i]
  64. }
  65. return len(ar) < len(br)
  66. }
  67. // keyFloat returns a float value for v if it is a number/bool
  68. // and whether it is a number/bool or not.
  69. func keyFloat(v reflect.Value) (f float64, ok bool) {
  70. switch v.Kind() {
  71. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  72. return float64(v.Int()), true
  73. case reflect.Float32, reflect.Float64:
  74. return v.Float(), true
  75. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  76. return float64(v.Uint()), true
  77. case reflect.Bool:
  78. if v.Bool() {
  79. return 1, true
  80. }
  81. return 0, true
  82. }
  83. return 0, false
  84. }
  85. // numLess returns whether a < b.
  86. // a and b must necessarily have the same kind.
  87. func numLess(a, b reflect.Value) bool {
  88. switch a.Kind() {
  89. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  90. return a.Int() < b.Int()
  91. case reflect.Float32, reflect.Float64:
  92. return a.Float() < b.Float()
  93. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  94. return a.Uint() < b.Uint()
  95. case reflect.Bool:
  96. return !a.Bool() && b.Bool()
  97. }
  98. panic("not a number")
  99. }