github.com/joomcode/cue@v0.4.4-0.20221111115225-539fe3512047/pkg/list/sort.go (about) 1 // Copyright 2018 The CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Copyright 2018 The Go Authors. All rights reserved. 16 // Use of this source code is governed by a BSD-style 17 // license that can be found in the LICENSE file. 18 19 package list 20 21 import ( 22 "sort" 23 24 "github.com/joomcode/cue/cue" 25 ) 26 27 // valueSorter defines a sort.Interface; implemented in cue/builtinutil.go. 28 type valueSorter struct { 29 a []cue.Value 30 cmp cue.Value 31 err error 32 } 33 34 func (s *valueSorter) ret() ([]cue.Value, error) { 35 if s.err != nil { 36 return nil, s.err 37 } 38 // The input slice is already a copy and that we can modify it safely. 39 return s.a, nil 40 } 41 42 func (s *valueSorter) Len() int { return len(s.a) } 43 func (s *valueSorter) Swap(i, j int) { s.a[i], s.a[j] = s.a[j], s.a[i] } 44 func (s *valueSorter) Less(i, j int) bool { 45 v := s.cmp.Fill(s.a[i], "x") 46 v = v.Fill(s.a[j], "y") 47 isLess, err := v.Lookup("less").Bool() 48 if err != nil && s.err == nil { 49 s.err = err 50 return true 51 } 52 return isLess 53 } 54 55 // Sort sorts data while keeping the original order of equal elements. 56 // It does O(n*log(n)) comparisons. 57 // 58 // cmp is a struct of the form {T: _, x: T, y: T, less: bool}, where 59 // less should reflect x < y. 60 // 61 // Example: 62 // 63 // Sort([2, 3, 1], list.Ascending) 64 // 65 // Sort{{a: 2}, {a: 3}, {a: 1}, {x: {}, y: {}, less: x.a < y.a}} 66 // 67 func Sort(list []cue.Value, cmp cue.Value) (sorted []cue.Value, err error) { 68 s := valueSorter{list, cmp, nil} 69 // The input slice is already a copy and that we can modify it safely. 70 sort.Stable(&s) 71 return s.ret() 72 } 73 74 // Deprecated: use Sort, which is always stable 75 func SortStable(list []cue.Value, cmp cue.Value) (sorted []cue.Value, err error) { 76 s := valueSorter{list, cmp, nil} 77 sort.Stable(&s) 78 return s.ret() 79 } 80 81 // Strings sorts a list of strings in increasing order. 82 func SortStrings(a []string) []string { 83 sort.Strings(a) 84 return a 85 } 86 87 // IsSorted tests whether a list is sorted. 88 // 89 // See Sort for an example comparator. 90 func IsSorted(list []cue.Value, cmp cue.Value) bool { 91 s := valueSorter{list, cmp, nil} 92 return sort.IsSorted(&s) 93 } 94 95 // IsSortedStrings tests whether a list is a sorted lists of strings. 96 func IsSortedStrings(a []string) bool { 97 return sort.StringsAreSorted(a) 98 }