github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/brutecheck/main.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "go/format" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 ) 12 13 func main() { 14 var keywords = []string{ 15 "break", "case", "chan", "const", "continue", 16 "default", "defer", "else", "fallthrough", "for", "func", "go", 17 "goto", "if", "import", "interface", "map", "package", "range", "return", 18 "select", "struct", "switch", "type", "var", 19 } 20 21 allfuncs := []string{} 22 23 generators := []Generator{ 24 LengthSingle{}, 25 Uint64Switch{}, 26 MapCheck{}, 27 TwoHashShift{}, 28 TwoHashShiftTable{}, 29 TwoHashShiftAlt{}, 30 TwoHashShiftTableAlt{}, 31 } 32 for _, gen := range generators { 33 genname := strings.ToLower(fmt.Sprintf("%T", gen)) 34 genname = strings.TrimPrefix(genname, "main.") 35 36 p := &BasicPrinter{} 37 p.F("package check\n\n") 38 gen.Generate(p, append([]string{}, keywords...)) 39 40 emitfile(filepath.Join("check", genname)+".go", p.Bytes()) 41 42 allfuncs = append(allfuncs, p.FuncNames()...) 43 } 44 45 { 46 p := &BasicPrinter{} 47 p.F("package main\n\n") 48 p.F("import . \"github.com/egonelbre/exp/brutecheck/check\"\n\n") 49 for _, fn := range allfuncs { 50 p.F("func Bench%s(words []string, repeat int) int {\n", fn) 51 p.F("var count int\n") 52 p.F("for i := 0; i < repeat; i++ {\n") 53 p.F("for _, word := range words {\n") 54 p.F("if %s(word) { count++ }\n", fn) 55 p.F("}\n") 56 p.F("}\n") 57 p.F("return count\n") 58 p.F("}\n\n") 59 } 60 emitfile(filepath.Join("bench", "bench.go"), p.Bytes()) 61 } 62 63 { 64 p := &BasicPrinter{} 65 p.F("package main\n\n") 66 p.F("type Bench struct { Name string; Fn func([]string, int) int }\n\n") 67 p.F("var AllBenches = []Bench{\n") 68 for _, fn := range allfuncs { 69 p.F("{Name:%q, Fn: Bench%s},\n", fn, fn) 70 } 71 p.F("}") 72 emitfile(filepath.Join("bench", "list.go"), p.Bytes()) 73 } 74 } 75 76 func emitfile(name string, data []byte) { 77 formatted, err := format.Source(data) 78 if err != nil { 79 fmt.Fprintf(os.Stderr, "failed to format: %v\n", err) 80 fmt.Fprintf(os.Stderr, "-----") 81 if len(data) > 1000 { 82 data = data[:1000] 83 } 84 fmt.Fprint(os.Stderr, string(data)) 85 os.Exit(1) 86 } 87 88 err = ioutil.WriteFile(name, formatted, 0644) 89 if err != nil { 90 fmt.Fprintf(os.Stderr, "failed to write: %v\n", err) 91 os.Exit(1) 92 } 93 } 94 95 type Generator interface { 96 Generate(p Printer, keywords []string) 97 } 98 99 type Printer interface { 100 FuncName(fnname string) 101 FuncNames() []string 102 103 F(format string, args ...interface{}) 104 Bytes() []byte 105 } 106 107 type BasicPrinter struct { 108 Funcs []string 109 Buffer bytes.Buffer 110 } 111 112 func (p *BasicPrinter) FuncName(fnname string) { 113 p.Funcs = append(p.Funcs, fnname) 114 } 115 116 func (p *BasicPrinter) FuncNames() []string { 117 return p.Funcs 118 } 119 120 func (p *BasicPrinter) F(format string, args ...interface{}) { 121 fmt.Fprintf(&p.Buffer, format, args...) 122 } 123 124 func (p *BasicPrinter) Bytes() []byte { 125 return p.Buffer.Bytes() 126 }