261 lines
6.2 KiB
Go
261 lines
6.2 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// Variable represents a configuration variable with name, value, and optional comment
|
|
type Variable struct {
|
|
name string
|
|
value string
|
|
comment string
|
|
}
|
|
|
|
// NewVariable creates a new variable
|
|
func NewVariable(name, value, comment string) *Variable {
|
|
return &Variable{
|
|
name: name,
|
|
value: value,
|
|
comment: comment,
|
|
}
|
|
}
|
|
|
|
// GetName returns the variable name
|
|
func (v *Variable) GetName() string {
|
|
return v.name
|
|
}
|
|
|
|
// GetValue returns the variable value
|
|
func (v *Variable) GetValue() string {
|
|
return v.value
|
|
}
|
|
|
|
// GetComment returns the variable comment
|
|
func (v *Variable) GetComment() string {
|
|
return v.comment
|
|
}
|
|
|
|
// GetNameValuePair returns the name and value as a single string
|
|
func (v *Variable) GetNameValuePair() string {
|
|
return fmt.Sprintf("%s %s", v.name, v.value)
|
|
}
|
|
|
|
// SetValue updates the variable value
|
|
func (v *Variable) SetValue(value string) {
|
|
v.value = value
|
|
}
|
|
|
|
// Variables manages a collection of configuration variables
|
|
type Variables struct {
|
|
variables map[string]*Variable
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// NewVariables creates a new variables manager
|
|
func NewVariables() *Variables {
|
|
return &Variables{
|
|
variables: make(map[string]*Variable),
|
|
}
|
|
}
|
|
|
|
// AddVariable adds a variable to the collection
|
|
func (v *Variables) AddVariable(variable *Variable) {
|
|
v.mutex.Lock()
|
|
defer v.mutex.Unlock()
|
|
|
|
v.variables[variable.name] = variable
|
|
}
|
|
|
|
// FindVariable finds a variable by exact name
|
|
func (v *Variables) FindVariable(name string) *Variable {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
return v.variables[name]
|
|
}
|
|
|
|
// GetVariable is an alias for FindVariable for convenience
|
|
func (v *Variables) GetVariable(name string) *Variable {
|
|
return v.FindVariable(name)
|
|
}
|
|
|
|
// GetVariables returns all variables that contain the partial name
|
|
func (v *Variables) GetVariables(partialName string) []*Variable {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
results := make([]*Variable, 0)
|
|
partialLower := strings.ToLower(partialName)
|
|
|
|
for name, variable := range v.variables {
|
|
if strings.Contains(strings.ToLower(name), partialLower) {
|
|
results = append(results, variable)
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// GetAllVariables returns all variables in the collection
|
|
func (v *Variables) GetAllVariables() map[string]*Variable {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
// Return a copy to prevent external modification
|
|
result := make(map[string]*Variable)
|
|
for name, variable := range v.variables {
|
|
result[name] = variable
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// GetVariableNames returns all variable names
|
|
func (v *Variables) GetVariableNames() []string {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
names := make([]string, 0, len(v.variables))
|
|
for name := range v.variables {
|
|
names = append(names, name)
|
|
}
|
|
|
|
return names
|
|
}
|
|
|
|
// SetVariable sets or updates a variable value
|
|
func (v *Variables) SetVariable(name, value string) {
|
|
v.mutex.Lock()
|
|
defer v.mutex.Unlock()
|
|
|
|
if variable, exists := v.variables[name]; exists {
|
|
variable.SetValue(value)
|
|
} else {
|
|
// Create new variable if it doesn't exist
|
|
v.variables[name] = NewVariable(name, value, "")
|
|
}
|
|
}
|
|
|
|
// DeleteVariable removes a variable by name
|
|
func (v *Variables) DeleteVariable(name string) bool {
|
|
v.mutex.Lock()
|
|
defer v.mutex.Unlock()
|
|
|
|
if _, exists := v.variables[name]; exists {
|
|
delete(v.variables, name)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// ClearVariables removes all variables
|
|
func (v *Variables) ClearVariables() {
|
|
v.mutex.Lock()
|
|
defer v.mutex.Unlock()
|
|
|
|
v.variables = make(map[string]*Variable)
|
|
}
|
|
|
|
// Count returns the number of variables
|
|
func (v *Variables) Count() int {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
return len(v.variables)
|
|
}
|
|
|
|
// HasVariable checks if a variable exists
|
|
func (v *Variables) HasVariable(name string) bool {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
_, exists := v.variables[name]
|
|
return exists
|
|
}
|
|
|
|
// GetVariableValue returns just the value of a variable, or empty string if not found
|
|
func (v *Variables) GetVariableValue(name string) string {
|
|
if variable := v.FindVariable(name); variable != nil {
|
|
return variable.GetValue()
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetVariableValueWithDefault returns the value of a variable, or a default if not found
|
|
func (v *Variables) GetVariableValueWithDefault(name, defaultValue string) string {
|
|
if variable := v.FindVariable(name); variable != nil {
|
|
return variable.GetValue()
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
// GetVariableAsInt attempts to parse a variable value as an integer
|
|
func (v *Variables) GetVariableAsInt(name string, defaultValue int) int {
|
|
if variable := v.FindVariable(name); variable != nil {
|
|
var intValue int
|
|
if _, err := fmt.Sscanf(variable.GetValue(), "%d", &intValue); err == nil {
|
|
return intValue
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
// GetVariableAsFloat attempts to parse a variable value as a float
|
|
func (v *Variables) GetVariableAsFloat(name string, defaultValue float64) float64 {
|
|
if variable := v.FindVariable(name); variable != nil {
|
|
var floatValue float64
|
|
if _, err := fmt.Sscanf(variable.GetValue(), "%f", &floatValue); err == nil {
|
|
return floatValue
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
// GetVariableAsBool attempts to parse a variable value as a boolean
|
|
func (v *Variables) GetVariableAsBool(name string, defaultValue bool) bool {
|
|
if variable := v.FindVariable(name); variable != nil {
|
|
value := strings.ToLower(variable.GetValue())
|
|
switch value {
|
|
case "true", "1", "yes", "on", "enabled":
|
|
return true
|
|
case "false", "0", "no", "off", "disabled":
|
|
return false
|
|
}
|
|
}
|
|
return defaultValue
|
|
}
|
|
|
|
// Clone creates a deep copy of the variables collection
|
|
func (v *Variables) Clone() *Variables {
|
|
v.mutex.RLock()
|
|
defer v.mutex.RUnlock()
|
|
|
|
newVars := NewVariables()
|
|
for name, variable := range v.variables {
|
|
newVar := NewVariable(variable.name, variable.value, variable.comment)
|
|
newVars.variables[name] = newVar
|
|
}
|
|
|
|
return newVars
|
|
}
|
|
|
|
// Merge merges another Variables collection into this one
|
|
// If overwrite is true, existing variables will be overwritten
|
|
func (v *Variables) Merge(other *Variables, overwrite bool) {
|
|
if other == nil {
|
|
return
|
|
}
|
|
|
|
v.mutex.Lock()
|
|
defer v.mutex.Unlock()
|
|
|
|
otherVars := other.GetAllVariables()
|
|
for name, variable := range otherVars {
|
|
if _, exists := v.variables[name]; !exists || overwrite {
|
|
v.variables[name] = NewVariable(variable.name, variable.value, variable.comment)
|
|
}
|
|
}
|
|
} |