mirror of
https://github.com/TeaOSLab/EdgeCommon.git
synced 2025-11-04 21:50:26 +08:00
104 lines
2.3 KiB
Go
104 lines
2.3 KiB
Go
package configutils
|
||
|
||
import (
|
||
"regexp"
|
||
"strings"
|
||
"sync"
|
||
)
|
||
|
||
// VariableHolder 变量信息存储类型
|
||
type VariableHolder string
|
||
type VariableHolders = []interface{}
|
||
|
||
var variableMapping = map[string][]interface{}{} // source => [holder1, ...]
|
||
var variableLocker = sync.RWMutex{}
|
||
var regexpNamedVariable = regexp.MustCompile(`\${[\w.-]+}`)
|
||
|
||
// ParseVariables 分析变量
|
||
func ParseVariables(source string, replacer func(varName string) (value string)) string {
|
||
if len(source) == 0 {
|
||
return ""
|
||
}
|
||
|
||
variableLocker.RLock()
|
||
holders, found := variableMapping[source]
|
||
variableLocker.RUnlock()
|
||
if !found {
|
||
holders = ParseHolders(source)
|
||
variableLocker.Lock()
|
||
variableMapping[source] = holders
|
||
variableLocker.Unlock()
|
||
}
|
||
|
||
// no variables
|
||
if len(holders) == 0 {
|
||
return source
|
||
}
|
||
|
||
// 只有一个占位时,我们快速返回
|
||
if len(holders) == 1 {
|
||
var h = holders[0]
|
||
holder, ok := h.(VariableHolder)
|
||
if ok {
|
||
return replacer(string(holder))
|
||
}
|
||
return source
|
||
}
|
||
|
||
// 多个占位时,使用Builder
|
||
var builder = strings.Builder{}
|
||
for _, h := range holders {
|
||
holder, ok := h.(VariableHolder)
|
||
if ok {
|
||
builder.WriteString(replacer(string(holder)))
|
||
} else {
|
||
builder.Write(h.([]byte))
|
||
}
|
||
}
|
||
return builder.String()
|
||
}
|
||
|
||
// 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 判断是否有变量
|
||
func HasVariables(source string) bool {
|
||
if len(source) == 0 {
|
||
return false
|
||
}
|
||
return regexpNamedVariable.MatchString(source)
|
||
}
|