package config import ( "github.com/safing/portmaster/base/log" ) type ( // StringOption defines the returned function by GetAsString. StringOption func() string // StringArrayOption defines the returned function by GetAsStringArray. StringArrayOption func() []string // IntOption defines the returned function by GetAsInt. IntOption func() int64 // BoolOption defines the returned function by GetAsBool. BoolOption func() bool ) func getValueCache(name string, option *Option, requestedType OptionType) (*Option, *valueCache) { // get option if option == nil { var err error option, err = GetOption(name) if err != nil { log.Errorf("config: request for unregistered option: %s", name) return nil, nil } } // Check the option type, no locking required as // OptType is immutable once it is set if requestedType != option.OptType { log.Errorf("config: bad type: requested %s as %s, but is %s", name, getTypeName(requestedType), getTypeName(option.OptType)) return option, nil } option.Lock() defer option.Unlock() // check release level if option.ReleaseLevel <= getReleaseLevel() && option.activeValue != nil { return option, option.activeValue } if option.activeDefaultValue != nil { return option, option.activeDefaultValue } return option, option.activeFallbackValue } // GetAsString returns a function that returns the wanted string with high performance. func GetAsString(name string, fallback string) StringOption { valid := getValidityFlag() option, valueCache := getValueCache(name, nil, OptTypeString) value := fallback if valueCache != nil { value = valueCache.stringVal } return func() string { if !valid.IsSet() { valid = getValidityFlag() option, valueCache = getValueCache(name, option, OptTypeString) if valueCache != nil { value = valueCache.stringVal } else { value = fallback } } return value } } // GetAsStringArray returns a function that returns the wanted string with high performance. func GetAsStringArray(name string, fallback []string) StringArrayOption { valid := getValidityFlag() option, valueCache := getValueCache(name, nil, OptTypeStringArray) value := fallback if valueCache != nil { value = valueCache.stringArrayVal } return func() []string { if !valid.IsSet() { valid = getValidityFlag() option, valueCache = getValueCache(name, option, OptTypeStringArray) if valueCache != nil { value = valueCache.stringArrayVal } else { value = fallback } } return value } } // GetAsInt returns a function that returns the wanted int with high performance. func GetAsInt(name string, fallback int64) IntOption { valid := getValidityFlag() option, valueCache := getValueCache(name, nil, OptTypeInt) value := fallback if valueCache != nil { value = valueCache.intVal } return func() int64 { if !valid.IsSet() { valid = getValidityFlag() option, valueCache = getValueCache(name, option, OptTypeInt) if valueCache != nil { value = valueCache.intVal } else { value = fallback } } return value } } // GetAsBool returns a function that returns the wanted int with high performance. func GetAsBool(name string, fallback bool) BoolOption { valid := getValidityFlag() option, valueCache := getValueCache(name, nil, OptTypeBool) value := fallback if valueCache != nil { value = valueCache.boolVal } return func() bool { if !valid.IsSet() { valid = getValidityFlag() option, valueCache = getValueCache(name, option, OptTypeBool) if valueCache != nil { value = valueCache.boolVal } else { value = fallback } } return value } } /* func getAndFindValue(key string) interface{} { optionsLock.RLock() option, ok := options[key] optionsLock.RUnlock() if !ok { log.Errorf("config: request for unregistered option: %s", key) return nil } return option.findValue() } */ /* // findValue finds the preferred value in the user or default config. func (option *Option) findValue() interface{} { // lock option option.Lock() defer option.Unlock() if option.ReleaseLevel <= getReleaseLevel() && option.activeValue != nil { return option.activeValue } if option.activeDefaultValue != nil { return option.activeDefaultValue } return option.DefaultValue } */