github.com/songzhibin97/gkit@v1.2.13/structure/skipmap/types_gen.go (about) 1 // Copyright 2021 ByteDance Inc. 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 //go:build ignore 16 // +build ignore 17 18 package main 19 20 import ( 21 "bytes" 22 "go/format" 23 "io/ioutil" 24 "os" 25 "strings" 26 ) 27 28 func main() { 29 f, err := os.Open("skipmap.go") 30 if err != nil { 31 panic(err) 32 } 33 filedata, err := ioutil.ReadAll(f) 34 if err != nil { 35 panic(err) 36 } 37 38 w := new(bytes.Buffer) 39 w.WriteString(`// Copyright 2021 ByteDance Inc. 40 // 41 // Licensed under the Apache License, Version 2.0 (the "License"); 42 // you may not use this file except in compliance with the License. 43 // You may obtain a copy of the License at 44 // 45 // http://www.apache.org/licenses/LICENSE-2.0 46 // 47 // Unless required by applicable law or agreed to in writing, software 48 // distributed under the License is distributed on an "AS IS" BASIS, 49 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 50 // See the License for the specific language governing permissions and 51 // limitations under the License. 52 53 `) 54 // Step 1. Add file header 55 w.WriteString(`// Code generated by go run types_gen.go; DO NOT EDIT.` + "\r\n") 56 // Step 2. Add imports and package statement 57 w.WriteString(string(filedata)[strings.Index(string(filedata), "package skipmap") : strings.Index(string(filedata), ")\n")+1]) 58 // Step 3. Generate code for basic types 59 ts := []string{"Byte", "Float32", "Float64", "Int", "Int8", "Int16", "Int32", "Rune", "Uint", "Uint8", "Uint16", "Uint32", "Uint64", "Uintptr"} // all types need to be converted 60 for _, upper := range ts { 61 data := string(filedata) 62 // Step 4-1. Remove all string before import 63 data = data[strings.Index(data, ")\n")+1:] 64 // Step 4-2. Replace all cases 65 dataDesc := replace(data, upper, true) 66 dataAsc := replace(data, upper, false) 67 w.WriteString(dataAsc) 68 w.WriteString("\r\n") 69 w.WriteString(dataDesc) 70 w.WriteString("\r\n") 71 } 72 // Step 5. Generate string map 73 data := string(filedata) 74 data = data[strings.Index(data, ")\n")+1:] 75 datastring := replaceString(data) 76 w.WriteString(datastring) 77 w.WriteString("\r\n") 78 79 out, err := format.Source(w.Bytes()) 80 if err != nil { 81 panic(err) 82 } 83 84 if err := ioutil.WriteFile("types.go", out, 0660); err != nil { 85 panic(err) 86 } 87 } 88 89 func replace(data string, upper string, desc bool) string { 90 lower := strings.ToLower(upper) 91 92 var descstr string 93 if desc { 94 descstr = "Desc" 95 } 96 data = strings.Replace(data, "NewInt64", "New"+upper+descstr, -1) 97 data = strings.Replace(data, "newInt64Node", "new"+upper+"Node"+descstr, -1) 98 data = strings.Replace(data, "unlockInt64", "unlock"+upper+descstr, -1) 99 data = strings.Replace(data, "Int64Map", upper+"Map"+descstr, -1) 100 data = strings.Replace(data, "int64Node", lower+"Node"+descstr, -1) 101 data = strings.Replace(data, "key int64", "key "+lower, -1) 102 data = strings.Replace(data, "key int64", "key "+lower, -1) 103 data = strings.Replace(data, "key int64", "key "+lower, -1) 104 data = strings.Replace(data, "int64 skipmap", lower+" skipmap", -1) // comment 105 106 if desc { 107 // Special cases for DESC. 108 data = strings.Replace(data, "ascending", "descending", -1) 109 data = strings.Replace(data, "return n.key < key", "return n.key > key", -1) 110 } 111 return data 112 } 113 114 func replaceString(data string) string { 115 const ( 116 upper = "String" 117 lower = "string" 118 ) 119 120 // Add `score uint64` field. 121 data = strings.Replace(data, 122 `type int64Node struct { 123 key int64`, 124 `type int64Node struct { 125 key int64 126 score uint64`, -1) 127 128 data = strings.Replace(data, 129 `&int64Node{`, 130 `&int64Node{ 131 score: hash(key),`, -1) 132 133 // Refactor comparsion. 134 data = data + "\n" 135 data += `// Return 1 if n is bigger, 0 if equal, else -1. 136 func (n *stringNode) cmp(score uint64, key string) int { 137 if n.score > score { 138 return 1 139 } else if n.score == score { 140 return cmpstring(n.key, key) 141 } 142 return -1 143 }` 144 145 data = strings.Replace(data, 146 `.lessthan(key)`, 147 `.cmp(score, key) < 0`, -1) 148 data = strings.Replace(data, 149 `.equal(key)`, 150 `.cmp(score, key) == 0`, -1) 151 152 // Remove `lessthan` and `equal` 153 data = strings.Replace(data, 154 `func (n *int64Node) lessthan(key int64) bool { 155 return n.key < key 156 }`, "", -1) 157 data = strings.Replace(data, 158 `func (n *int64Node) equal(key int64) bool { 159 return n.key == key 160 }`, "", -1) 161 162 // Add "score := hash(key)" 163 data = addLineAfter(data, "func (s *Int64Map) findNodeDelete", "score := hash(key)") 164 data = addLineAfter(data, "func (s *Int64Map) findNode", "score := hash(key)") 165 data = addLineAfter(data, "func (s *Int64Map) Load", "score := hash(key)") 166 167 // Update new key "newInt64Node(0" 168 data = strings.Replace(data, 169 "newInt64Node(0", `newInt64Node(""`, -1) 170 171 data = strings.Replace(data, "NewInt64", "New"+upper, -1) 172 data = strings.Replace(data, "newInt64Node", "new"+upper+"Node", -1) 173 data = strings.Replace(data, "unlockInt64", "unlock"+upper, -1) 174 data = strings.Replace(data, "Int64Map", upper+"Map", -1) 175 data = strings.Replace(data, "int64Node", lower+"Node", -1) 176 data = strings.Replace(data, "key int64", "key "+lower, -1) 177 data = strings.Replace(data, "key int64", "key "+lower, -1) 178 data = strings.Replace(data, "key int64", "key "+lower, -1) 179 data = strings.Replace(data, "int64 skip map", lower+" skip map", -1) // comment 180 data = strings.Replace(data, " in ascending order", "", -1) // comment 181 182 return data 183 } 184 185 func lowerSlice(s []string) []string { 186 n := make([]string, len(s)) 187 for i, v := range s { 188 n[i] = strings.ToLower(v) 189 } 190 return n 191 } 192 193 func inSlice(s []string, val string) bool { 194 for _, v := range s { 195 if v == val { 196 return true 197 } 198 } 199 return false 200 } 201 202 func addLineAfter(src string, after string, added string) string { 203 all := strings.Split(string(src), "\n") 204 for i, v := range all { 205 if strings.Index(v, after) != -1 { 206 res := make([]string, len(all)+1) 207 for j := 0; j <= i; j++ { 208 res[j] = all[j] 209 } 210 res[i+1] = added 211 for j := i + 1; j < len(all); j++ { 212 res[j+1] = all[j] 213 } 214 return strings.Join(res, "\n") 215 } 216 } 217 panic("can not find:" + after) 218 }