github.com/jfcg/sorty@v1.2.0/sortyLen.go (about)

     1  /*	Copyright (c) 2021, Serhat Şevki Dinçer.
     2  	This Source Code Form is subject to the terms of the Mozilla Public
     3  	License, v. 2.0. If a copy of the MPL was not distributed with this
     4  	file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5  */
     6  
     7  package sorty
     8  
     9  import (
    10  	"reflect"
    11  	"unsafe"
    12  
    13  	"github.com/jfcg/sixb"
    14  )
    15  
    16  func extract(ar interface{}) (slc sixb.Slice, r int) {
    17  	t := reflect.TypeOf(ar)
    18  	if t.Kind() != reflect.Slice {
    19  		return
    20  	}
    21  	k := t.Elem().Kind()
    22  	if k == reflect.String {
    23  		r++
    24  	} else if k == reflect.Slice {
    25  		r--
    26  	} else {
    27  		return
    28  	}
    29  
    30  	v := reflect.ValueOf(ar)
    31  	p, l := v.Pointer(), v.Len()
    32  	slc = sixb.Slice{Data: unsafe.Pointer(p), Len: l, Cap: l}
    33  	return
    34  }
    35  
    36  // IsSortedLen returns 0 if ar is sorted 'by length' in ascending order, otherwise
    37  // it returns i > 0 with len(ar[i]) < len(ar[i-1]). ar's (underlying) type can be
    38  // []string or [][]T (for any type T), otherwise it panics.
    39  func IsSortedLen(ar interface{}) int {
    40  	slc, r := extract(ar)
    41  	if r == 0 {
    42  		panic("sorty: IsSortedLen: invalid input type")
    43  	}
    44  	if r > 0 {
    45  		s := *(*[]string)(unsafe.Pointer(&slc))
    46  		for i := len(s) - 1; i > 0; i-- {
    47  			if len(s[i]) < len(s[i-1]) {
    48  				return i
    49  			}
    50  		}
    51  		return 0
    52  	}
    53  	b := *(*[][]byte)(unsafe.Pointer(&slc))
    54  	for i := len(b) - 1; i > 0; i-- {
    55  		if len(b[i]) < len(b[i-1]) {
    56  			return i
    57  		}
    58  	}
    59  	return 0
    60  }
    61  
    62  // SortLen concurrently sorts ar 'by length' in ascending order. ar's (underlying)
    63  // type can be []string or [][]T (for any type T), otherwise it panics.
    64  func SortLen(ar interface{}) {
    65  	slc, r := extract(ar)
    66  	if r == 0 {
    67  		panic("sorty: SortLen: invalid input type")
    68  	}
    69  	if r > 0 {
    70  		s := *(*[]string)(unsafe.Pointer(&slc))
    71  		sortLenS(s)
    72  		return
    73  	}
    74  	b := *(*[][]byte)(unsafe.Pointer(&slc))
    75  	sortLenB(b)
    76  }