github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/collection/skipset/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("skipset.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 skipset") : strings.Index(string(filedata), ")\n")+1]) 58 // Step 3. Generate code for all basic types 59 ts := []string{"Float32", "Float64", "Int32", "Int16", "Int", "Uint64", "Uint32", "Uint16", "Uint"} // 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 set 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, "Int64Set", upper+"Set"+descstr, -1) 100 data = strings.Replace(data, "int64Node", lower+"Node"+descstr, -1) 101 data = strings.Replace(data, "value int64", "value "+lower, -1) 102 data = strings.Replace(data, "int64 skip set", lower+" skip set", -1) // comment 103 104 if desc { 105 // Special cases for DESC. 106 data = strings.Replace(data, "ascending", "descending", -1) 107 data = strings.Replace(data, "return n.value < value", "return n.value > value", -1) 108 } 109 return data 110 } 111 112 func replaceString(data string) string { 113 const ( 114 upper = "String" 115 lower = "string" 116 ) 117 118 // Add `score uint64` field. 119 data = strings.Replace(data, 120 `type int64Node struct { 121 value int64`, 122 `type int64Node struct { 123 value int64 124 score uint64`, -1) 125 126 data = strings.Replace(data, 127 `&int64Node{`, 128 `&int64Node{ 129 score: hash(value),`, -1) 130 131 // Refactor comparison. 132 data = data + "\n" 133 data += `// Return 1 if n is bigger, 0 if equal, else -1. 134 func (n *stringNode) cmp(score uint64, value string) int { 135 if n.score > score { 136 return 1 137 } else if n.score == score { 138 return cmpstring(n.value, value) 139 } 140 return -1 141 }` 142 143 data = strings.Replace(data, 144 `.lessthan(value)`, 145 `.cmp(score, value) < 0`, -1) 146 data = strings.Replace(data, 147 `.equal(value)`, 148 `.cmp(score, value) == 0`, -1) 149 150 // Remove `lessthan` and `equal` 151 data = strings.Replace(data, 152 `func (n *int64Node) lessthan(value int64) bool { 153 return n.value < value 154 }`, "", -1) 155 data = strings.Replace(data, 156 `func (n *int64Node) equal(value int64) bool { 157 return n.value == value 158 }`, "", -1) 159 160 // Add "score := hash(value)" 161 data = addLineAfter(data, "func (s *Int64Set) findNodeRemove", "score := hash(value)") 162 data = addLineAfter(data, "func (s *Int64Set) findNodeAdd", "score := hash(value)") 163 data = addLineAfter(data, "func (s *Int64Set) Contains", "score := hash(value)") 164 165 // Update new value "newInt64Node(0" 166 data = strings.Replace(data, 167 "newInt64Node(0", `newInt64Node(""`, -1) 168 169 data = strings.Replace(data, "NewInt64", "New"+upper, -1) 170 data = strings.Replace(data, "newInt64Node", "new"+upper+"Node", -1) 171 data = strings.Replace(data, "unlockInt64", "unlock"+upper, -1) 172 data = strings.Replace(data, "Int64Set", upper+"Set", -1) 173 data = strings.Replace(data, "int64Node", lower+"Node", -1) 174 data = strings.Replace(data, "value int64", "value "+lower, -1) 175 data = strings.Replace(data, "int64 skip set", lower+" skip set", -1) // comment 176 data = strings.Replace(data, " in ascending order", "", -1) // comment 177 178 return data 179 } 180 181 func lowerSlice(s []string) []string { 182 n := make([]string, len(s)) 183 for i, v := range s { 184 n[i] = strings.ToLower(v) 185 } 186 return n 187 } 188 189 func inSlice(s []string, val string) bool { 190 for _, v := range s { 191 if v == val { 192 return true 193 } 194 } 195 return false 196 } 197 198 func addLineAfter(src string, after string, added string) string { 199 all := strings.Split(string(src), "\n") 200 for i, v := range all { 201 if strings.Index(v, after) != -1 { 202 res := make([]string, len(all)+1) 203 for j := 0; j <= i; j++ { 204 res[j] = all[j] 205 } 206 res[i+1] = added 207 for j := i + 1; j < len(all); j++ { 208 res[j+1] = all[j] 209 } 210 return strings.Join(res, "\n") 211 } 212 } 213 panic("can not find:" + after) 214 }