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)) }