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  `