Files
EdgeCommon/pkg/configutils/variable.go

124 lines
2.8 KiB
Go
Raw Normal View History

2020-09-26 08:07:24 +08:00
package configutils
import (
"regexp"
"strings"
"sync"
)
2021-06-27 22:00:02 +08:00
// VariableHolder 变量信息存储类型
2020-09-26 08:07:24 +08:00
type VariableHolder string
2021-06-27 22:00:02 +08:00
type VariableHolders = []interface{}
2020-09-26 08:07:24 +08:00
2021-06-27 22:00:02 +08:00
var variableMapping = map[string][]interface{}{} // source => [holder1, ...]
2020-09-26 08:07:24 +08:00
var variableLocker = sync.RWMutex{}
2021-12-13 15:36:46 +08:00
var regexpNamedVariable = regexp.MustCompile(`\${[\w.-]+}`)
2020-09-26 08:07:24 +08:00
2022-04-04 19:44:45 +08:00
var stringBuilderPool = sync.Pool{
New: func() interface{} {
return &strings.Builder{}
},
}
2021-06-27 22:00:02 +08:00
// ParseVariables 分析变量
2020-09-26 08:07:24 +08:00
func ParseVariables(source string, replacer func(varName string) (value string)) string {
2022-04-04 16:42:56 +08:00
if len(source) == 0 {
return ""
}
2020-09-26 08:07:24 +08:00
variableLocker.RLock()
holders, found := variableMapping[source]
variableLocker.RUnlock()
if !found {
2021-06-27 22:00:02 +08:00
holders = ParseHolders(source)
2020-09-26 08:07:24 +08:00
variableLocker.Lock()
variableMapping[source] = holders
variableLocker.Unlock()
}
// no variables
if len(holders) == 0 {
return source
}
2021-12-13 15:31:03 +08:00
// 只有一个占位时,我们快速返回
if len(holders) == 1 {
var h = holders[0]
holder, ok := h.(VariableHolder)
if ok {
return replacer(string(holder))
}
return source
}
// 多个占位时使用Builder
2022-04-04 19:44:45 +08:00
var builder = stringBuilderPool.Get().(*strings.Builder)
builder.Reset()
defer stringBuilderPool.Put(builder)
2020-09-26 08:07:24 +08:00
for _, h := range holders {
holder, ok := h.(VariableHolder)
if ok {
2022-04-04 16:42:56 +08:00
builder.WriteString(replacer(string(holder)))
2020-09-26 08:07:24 +08:00
} else {
2022-04-04 16:42:56 +08:00
builder.Write(h.([]byte))
2020-09-26 08:07:24 +08:00
}
}
2022-04-04 16:42:56 +08:00
return builder.String()
2020-09-26 08:07:24 +08:00
}
2020-09-26 19:54:20 +08:00
2023-06-28 16:19:05 +08:00
func ParseVariablesError(source string, replacer func(varName string) (value string, err error)) (string, error) {
var resultErr error
var result = ParseVariables(source, func(varName string) (value string) {
replacedValue, err := replacer(varName)
if err != nil {
resultErr = err
}
return replacedValue
})
return result, resultErr
}
2021-06-27 22:00:02 +08:00
// ParseVariablesFromHolders 从占位中分析变量
func ParseVariablesFromHolders(holders VariableHolders, replacer func(varName string) (value string)) string {
// no variables
if len(holders) == 0 {
return ""
}
// replace
result := strings.Builder{}
for _, h := range holders {
holder, ok := h.(VariableHolder)
if ok {
result.WriteString(replacer(string(holder)))
} else {
result.Write(h.([]byte))
}
}
return result.String()
}
// ParseHolders 分析占位
func ParseHolders(source string) (holders VariableHolders) {
indexes := regexpNamedVariable.FindAllStringIndex(source, -1)
before := 0
for _, loc := range indexes {
holders = append(holders, []byte(source[before:loc[0]]))
holder := source[loc[0]+2 : loc[1]-1]
holders = append(holders, VariableHolder(holder))
before = loc[1]
}
if before < len(source) {
holders = append(holders, []byte(source[before:]))
}
return holders
}
// HasVariables 判断是否有变量
2020-09-26 19:54:20 +08:00
func HasVariables(source string) bool {
2022-04-04 16:42:56 +08:00
if len(source) == 0 {
return false
}
2020-09-26 19:54:20 +08:00
return regexpNamedVariable.MatchString(source)
}