优化缓存机制 补充错误码
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type ClientConfig struct {
|
||||
Types map[int]ClientValue
|
||||
TypeName2Index map[string]int
|
||||
Data map[string]map[int]string
|
||||
mu sync.RWMutex
|
||||
}
|
||||
|
||||
type ClientValue struct {
|
||||
Desc string
|
||||
Type string
|
||||
Name string
|
||||
}
|
||||
|
||||
func NewClientConfig() *ClientConfig {
|
||||
return &ClientConfig{
|
||||
Types: make(map[int]ClientValue),
|
||||
Data: make(map[string]map[int]string),
|
||||
TypeName2Index: make(map[string]int),
|
||||
mu: sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func NewClientConfigWithFile(filename string) (*ClientConfig, error) {
|
||||
c := NewClientConfig()
|
||||
return c, c.LoadFile(filename)
|
||||
}
|
||||
|
||||
func (c *ClientConfig) LoadFile(filename string) error {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.loadByReader(bufio.NewReader(file))
|
||||
}
|
||||
|
||||
func (c *ClientConfig) LoadByReader(reader io.Reader) error {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
return c.loadByReader(reader)
|
||||
}
|
||||
|
||||
func (c *ClientConfig) loadByReader(reader io.Reader) error {
|
||||
// 创建缓存读取 分隔符设置成 回车
|
||||
scan := bufio.NewScanner(reader)
|
||||
scan.Split(bufio.ScanLines)
|
||||
|
||||
var line int
|
||||
var types []string
|
||||
var desc []string
|
||||
|
||||
for scan.Scan() {
|
||||
line++
|
||||
|
||||
lineContent := strings.TrimSpace(scan.Text())
|
||||
if len(lineContent) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 去除注释
|
||||
split := strings.Split(lineContent, "//")
|
||||
if len(split) > 1 {
|
||||
lineContent = split[0]
|
||||
}
|
||||
|
||||
// 类型
|
||||
if line == 1 {
|
||||
types = strings.Split(lineContent, "\t")
|
||||
continue
|
||||
}
|
||||
|
||||
// 备注
|
||||
if line == 2 {
|
||||
desc = strings.Split(lineContent, "\t")
|
||||
continue
|
||||
}
|
||||
|
||||
// key
|
||||
if line == 3 {
|
||||
for i, t := range strings.Split(lineContent, "\t") {
|
||||
if len(types) < i {
|
||||
return fmt.Errorf("line %d: invalid type", line)
|
||||
}
|
||||
|
||||
if len(desc) < i {
|
||||
return fmt.Errorf("line %d: invalid desc", line)
|
||||
}
|
||||
|
||||
c.Types[i] = ClientValue{
|
||||
Desc: desc[i],
|
||||
Type: types[i],
|
||||
Name: t,
|
||||
}
|
||||
c.TypeName2Index[t] = i
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
var lineData = make(map[int]string)
|
||||
var lineKey string
|
||||
for i1, v1 := range strings.Split(lineContent, "\t") {
|
||||
if i1 == 0 {
|
||||
lineKey = strings.TrimSpace(v1)
|
||||
}
|
||||
lineData[i1] = strings.TrimSpace(v1)
|
||||
}
|
||||
if len(lineData) == 0 {
|
||||
continue
|
||||
}
|
||||
c.Data[lineKey] = lineData
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value 读取单个
|
||||
func (c *ClientConfig) Value(key string, objKey string) (ClientValue, string, error) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
l, is := c.Data[key]
|
||||
if !is {
|
||||
return ClientValue{}, "", fmt.Errorf("key %s not found", key)
|
||||
}
|
||||
index, is2 := c.TypeName2Index[objKey]
|
||||
if !is2 {
|
||||
return ClientValue{}, "", fmt.Errorf("objKey %s not found", objKey)
|
||||
}
|
||||
return c.Types[index], l[index], nil
|
||||
}
|
||||
|
||||
// ValueByLine 读取
|
||||
func (c *ClientConfig) ValueByLine(line map[int]string, key string) (ClientValue, string, error) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
index, is2 := c.TypeName2Index[key]
|
||||
if !is2 {
|
||||
return ClientValue{}, "", fmt.Errorf("objKey %s not found", key)
|
||||
}
|
||||
return c.Types[index], line[index], nil
|
||||
}
|
||||
|
||||
// LineByKey 通过Key获取一行
|
||||
func (c *ClientConfig) LineByKey(key string) map[int]string {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
return c.Data[key]
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"complie-erlang/cache"
|
||||
"complie-erlang/parser/zm_lib"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type ErrCode struct {
|
||||
codeMap map[string]bool
|
||||
ClientConfig *ClientConfig
|
||||
}
|
||||
|
||||
func NewErrCode(c *ClientConfig) *ErrCode {
|
||||
return &ErrCode{
|
||||
codeMap: make(map[string]bool),
|
||||
ClientConfig: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ErrCode) LoadWd() error {
|
||||
wdDir, err := zm_lib.FindPathByWd(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return e.iterationDir(wdDir)
|
||||
}
|
||||
|
||||
func (e *ErrCode) iterationDir(baseDir string) error {
|
||||
|
||||
dir, err := os.ReadDir(baseDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, d := range dir {
|
||||
if d.IsDir() {
|
||||
err = e.iterationDir(filepath.Join(filepath.Join(baseDir, d.Name())))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
path := filepath.Join(baseDir, d.Name())
|
||||
|
||||
if err = e.loadFile(path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ErrCode) loadFile(filename string) error {
|
||||
bytes, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 定义正则表达式
|
||||
// 注意:由于\?在Go的字符串中是一个特殊字符,我们使用\\?来表示一个问号。
|
||||
// 同时,由于双引号在正则表达式中有特殊含义,我们需要使用\\"来表示一个普通双引号。
|
||||
// 我们使用非贪婪匹配来确保只匹配到第一个双引号后的内容。
|
||||
re := regexp.MustCompile(`(?:\\?\?ThrowErr|throw)\("([^"]+)"\)`)
|
||||
|
||||
// 查找所有匹配项
|
||||
matches := re.FindAllStringSubmatch(string(bytes), -1)
|
||||
|
||||
// 提取并打印双引号内的内容
|
||||
for _, match := range matches {
|
||||
// match[0] 是整个匹配的字符串,match[1] 是第一个括号内的匹配(即双引号内的内容)
|
||||
if e.codeMap[match[1]] {
|
||||
continue
|
||||
}
|
||||
e.codeMap[match[1]] = true
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *ErrCode) PrintErrCode(c cache.Cache) error {
|
||||
fmt.Println(">")
|
||||
|
||||
for key := range e.codeMap {
|
||||
line := e.ClientConfig.LineByKey(key)
|
||||
if line == nil {
|
||||
val, is := c.Get(key)
|
||||
if is {
|
||||
fmt.Printf(" %s: %v[cache] \n", key, val)
|
||||
} else {
|
||||
fmt.Printf(" %s: %v \n", key, nil)
|
||||
}
|
||||
|
||||
} else {
|
||||
_, s, err := e.ClientConfig.ValueByLine(line, "UserCN")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s: %s \n", key, s)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package zm_lib
|
||||
|
||||
import (
|
||||
"complie-erlang/cache"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func PersistentFlagsStringVar(cmd *cobra.Command, varK *string, cache cache.Cache, globalKey string, defaultValue string, desc string) error {
|
||||
pluginKey := fmt.Sprintf("%s.%s", cmd.Use, globalKey)
|
||||
plugin, err := cache.GetDefault(pluginKey, defaultValue)
|
||||
cmd.PersistentFlags().StringVar(varK, globalKey, plugin.(string), fmt.Sprintf("%s (global.key:\"%s\")", desc, pluginKey))
|
||||
return err
|
||||
}
|
||||
@@ -67,6 +67,16 @@ func FindPathByBasePath(basefun func() (basePath string, err error), path string
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
path = filepath.Join(filepath.Dir(basePath), path)
|
||||
|
||||
info, err := os.Stat(basePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
path = filepath.Join(filepath.Dir(basePath), path)
|
||||
} else {
|
||||
path = filepath.Join(basePath, path)
|
||||
}
|
||||
|
||||
return path, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user