github.com/jxskiss/gopkg@v0.17.3/easy/sort_template.go (about) 1 // +build ignore 2 3 // This program generates sorting utilities for concrete types. 4 // It can be invoked by running `go generate`. 5 package main 6 7 import ( 8 "bytes" 9 "go/format" 10 "io/ioutil" 11 "log" 12 "text/template" 13 "time" 14 ) 15 16 type Type struct { 17 Type string 18 SliceType string 19 } 20 21 func main() { 22 var targetTypes = []Type{ 23 {"int8", "Int8s"}, 24 {"uint8", "Uint8s"}, 25 {"int16", "Int16s"}, 26 {"uint16", "Uint16s"}, 27 {"int32", "Int32s"}, 28 {"uint32", "Uint32s"}, 29 {"int", "Ints"}, 30 {"uint", "Uints"}, 31 {"uintptr", "Uintptrs"}, 32 {"int64", "Int64s"}, 33 {"uint64", "Uint64s"}, 34 {"float32", "Float32s"}, 35 {"float64", "Float64s"}, 36 {"string", "Strings"}, 37 } 38 39 tmpl := template.New("") 40 tmpl = template.Must(tmpl.New("header").Parse(headertmpl)) 41 tmpl = template.Must(tmpl.New("code").Parse(codetmpl)) 42 43 var buf bytes.Buffer 44 if err := tmpl.ExecuteTemplate(&buf, "header", map[string]interface{}{ 45 "Now": time.Now().Format(time.RFC3339), 46 }); err != nil { 47 log.Fatal(err) 48 } 49 for _, t := range targetTypes { 50 if err := tmpl.ExecuteTemplate(&buf, "code", t); err != nil { 51 log.Fatal(err) 52 } 53 } 54 out, err := format.Source(buf.Bytes()) 55 if err != nil { 56 log.Fatal(err) 57 } 58 if err = ioutil.WriteFile("sort_gen.go", out, 0644); err != nil { 59 log.Fatal(err) 60 } 61 } 62 63 var headertmpl = `// Code generated by go generate at {{ .Now }}; DO NOT EDIT. 64 65 package easy 66 67 //go:generate go run sort_template.go 68 69 import "sort" 70 71 ` 72 73 var codetmpl = ` 74 75 // {{ .SliceType }}Asc attaches the methods of sort.Interface to []{{ .Type }}, sorting in ascending order. 76 type {{ .SliceType }}Asc []{{ .Type }} 77 78 func (x {{ .SliceType }}Asc) Len() int { return len(x) } 79 func (x {{ .SliceType }}Asc) Less(i, j int) bool { return x[i] < x[j] } 80 func (x {{ .SliceType }}Asc) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 81 82 // Sort is a convenience method which calls sort.Sort(x). 83 func (x {{ .SliceType }}Asc) Sort() { sort.Sort(x) } 84 85 // {{ .SliceType }}Desc attaches the methods of sort.Interface to []{{ .Type }}, sorting in descending order. 86 type {{ .SliceType }}Desc []{{ .Type }} 87 88 func (x {{ .SliceType }}Desc) Len() int { return len(x) } 89 func (x {{ .SliceType }}Desc) Less(i, j int) bool { return x[i] > x[j] } 90 func (x {{ .SliceType }}Desc) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 91 92 // Sort is a convenience method which calls sort.Sort(x). 93 func (x {{ .SliceType }}Desc) Sort() { sort.Sort(x) } 94 95 // Sort{{ .SliceType }}Asc is a convenience method which calls sort.Sort({{ .SliceType }}Asc(x)). 96 func Sort{{ .SliceType }}Asc(x []{{ .Type }}) { sort.Sort({{ .SliceType }}Asc(x)) } 97 98 // Sort{{ .SliceType }}Desc is a convenience method which calls sort.Sort({{ .SliceType }}Desc(x)). 99 func Sort{{ .SliceType }}Desc(x []{{ .Type }}) { sort.Sort({{ .SliceType }}Desc(x)) } 100 101 // {{ .SliceType }}AreSortedAsc is a convenience method which calls sort.IsSorted({{ .SliceType }}Asc(x)). 102 func {{ .SliceType }}AreSortedAsc(x []{{ .Type }}) bool { return sort.IsSorted({{ .SliceType }}Asc(x)) } 103 104 // {{ .SliceType }}AreSortedDesc is a convenience method which calls sort.IsSorted({{ .SliceType }}Desc(x)). 105 func {{ .SliceType }}AreSortedDesc(x []{{ .Type }}) bool { return sort.IsSorted({{ .SliceType }}Desc(x)) } 106 107 // InSorted{{ .SliceType }} tells whether elem is in a sorted {{ .Type }} slice. 108 // The given slice must be sorted in either ascending order or 109 // descending, else it may give incorrect result. 110 func InSorted{{ .SliceType }}(slice []{{ .Type }}, elem {{ .Type }}) bool { 111 length := len(slice) 112 if length == 0 { 113 return false 114 } 115 if length == 1 || slice[0] == slice[length-1] { 116 return slice[0] == elem 117 } 118 119 var less func(i int) bool 120 if slice[0] <= slice[length-1] { 121 // ascending order 122 less = func(i int) bool { return slice[i] >= elem } 123 } else { 124 // descending order 125 less = func(i int) bool { return slice[i] <= elem } 126 } 127 i := sort.Search(length, less) 128 return i < len(slice) && slice[i] == elem 129 } 130 `