github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/collection/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{"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 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 comparison.
   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  }