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 }