另客网go项目公用的代码库

sorter.go 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. if ar[i] == '0' || br[i] == '0' {
  52. for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
  53. if ar[j] != '0' {
  54. an = 1
  55. bn = 1
  56. break
  57. }
  58. }
  59. }
  60. for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
  61. an = an*10 + int64(ar[ai]-'0')
  62. }
  63. for bi = i; bi < len(br) && unicode.IsDigit(br[bi]); bi++ {
  64. bn = bn*10 + int64(br[bi]-'0')
  65. }
  66. if an != bn {
  67. return an < bn
  68. }
  69. if ai != bi {
  70. return ai < bi
  71. }
  72. return ar[i] < br[i]
  73. }
  74. return len(ar) < len(br)
  75. }
  76. // keyFloat returns a float value for v if it is a number/bool
  77. // and whether it is a number/bool or not.
  78. func keyFloat(v reflect.Value) (f float64, ok bool) {
  79. switch v.Kind() {
  80. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  81. return float64(v.Int()), true
  82. case reflect.Float32, reflect.Float64:
  83. return v.Float(), true
  84. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  85. return float64(v.Uint()), true
  86. case reflect.Bool:
  87. if v.Bool() {
  88. return 1, true
  89. }
  90. return 0, true
  91. }
  92. return 0, false
  93. }
  94. // numLess returns whether a < b.
  95. // a and b must necessarily have the same kind.
  96. func numLess(a, b reflect.Value) bool {
  97. switch a.Kind() {
  98. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  99. return a.Int() < b.Int()
  100. case reflect.Float32, reflect.Float64:
  101. return a.Float() < b.Float()
  102. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  103. return a.Uint() < b.Uint()
  104. case reflect.Bool:
  105. return !a.Bool() && b.Bool()
  106. }
  107. panic("not a number")
  108. }