github.com/puellanivis/breton@v0.2.16/lib/sort/runes.go (about) 1 package sort 2 3 import ( 4 "math/bits" 5 "sort" 6 "unicode" 7 ) 8 9 // RuneSliceSlice attaches the methods of sort.Interface to [][]rune, sorting in increasing order. 10 type RuneSliceSlice [][]rune 11 12 // Len implements sort.Interface. 13 func (p RuneSliceSlice) Len() int { return len(p) } 14 15 // Less implements sort.Interface. 16 func (p RuneSliceSlice) Less(i, j int) bool { return p.cmp(p[i], p[j]) < 0 } 17 18 // Swap implements sort.Interface. 19 func (p RuneSliceSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 20 21 func (p RuneSliceSlice) cmp(x, y []rune) int { 22 for n, r := range x { 23 if n >= len(y) { 24 return -1 25 } 26 if r < y[n] { 27 return -1 28 } 29 if r > y[n] { 30 return 1 31 } 32 } 33 return 0 34 } 35 36 // Compare implements Comparer. 37 func (p RuneSliceSlice) Compare(i, j int) int { 38 return p.cmp(p[i], p[j]) 39 } 40 41 // CompareFunc implements Comparer. 42 func (p RuneSliceSlice) CompareFunc(x interface{}) func(int) int { 43 e := x.([]rune) 44 return func(i int) int { 45 return p.cmp(p[i], e) 46 } 47 } 48 49 var runeMSB = int(31 - bits.LeadingZeros32(uint32(unicode.MaxRune))) 50 51 // RadixRange implements RadixInterface. 52 func (p RuneSliceSlice) RadixRange() (int, int) { 53 r := 0 54 for _, s := range p { 55 if len(s) > r { 56 r = len(s) 57 } 58 } 59 return 0, r * runeMSB 60 } 61 62 // RadixFunc implements RadixInterface. 63 func (p RuneSliceSlice) RadixFunc(r int) RadixTest { 64 n := r / runeMSB 65 mask := rune(1) << uint(runeMSB-(r%runeMSB)) 66 67 return func(i int) bool { 68 if n >= len(p[i]) { 69 return false 70 } 71 72 return p[i][n]&mask != 0 73 } 74 } 75 76 // Sort is a convenience method. 77 func (p RuneSliceSlice) Sort() { radix(p) } 78 79 // Search is a convenience method. 80 func (p RuneSliceSlice) Search(x []rune) int { return SearchRuneSlices(p, x) } 81 82 // Radix is a convenience method. 83 func (p RuneSliceSlice) Radix() { radix(p) } 84 85 // RuneSlices sorts a slice of []runes in increasing order. 86 func RuneSlices(a [][]rune) { radix(RuneSliceSlice(a)) } 87 88 // SearchRuneSlices searches for x in a sorted slice of []runes and returns the index 89 // as specified by sort.Search. The return value is the index to insert x if x is not present (it could be len(a)). 90 // The slice must be sorted in ascending order. 91 func SearchRuneSlices(a [][]rune, x []rune) int { 92 p := RuneSliceSlice(a) 93 94 return sort.Search(len(a), func(i int) bool { return p.cmp(a[i], x) >= 0 }) 95 } 96 97 // RuneSlicesAreSorted tests whether a slice of []runes is sorted in increasing order. 98 func RuneSlicesAreSorted(a [][]rune) bool { return sort.IsSorted(RuneSliceSlice(a)) }