Initial QSfera import
This commit is contained in:
+304
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
Package config is a go config management implement. support YAML,TOML,JSON,INI,HCL format.
|
||||
|
||||
Source code and other details for the project are available at GitHub:
|
||||
|
||||
https://github.com/gookit/config
|
||||
|
||||
JSON format content example:
|
||||
|
||||
{
|
||||
"name": "app",
|
||||
"debug": false,
|
||||
"baseKey": "value",
|
||||
"age": 123,
|
||||
"envKey": "${SHELL}",
|
||||
"envKey1": "${NotExist|defValue}",
|
||||
"map1": {
|
||||
"key": "val",
|
||||
"key1": "val1",
|
||||
"key2": "val2"
|
||||
},
|
||||
"arr1": [
|
||||
"val",
|
||||
"val1",
|
||||
"val2"
|
||||
],
|
||||
"lang": {
|
||||
"dir": "res/lang",
|
||||
"defLang": "en",
|
||||
"allowed": {
|
||||
"en": "val",
|
||||
"zh-CN": "val2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Usage please see example(more example please see examples folder in the lib):
|
||||
*/
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// There are supported config format
|
||||
const (
|
||||
Ini = "ini"
|
||||
Hcl = "hcl"
|
||||
Yml = "yml"
|
||||
JSON = "json"
|
||||
Yaml = "yaml"
|
||||
Toml = "toml"
|
||||
Prop = "properties"
|
||||
)
|
||||
|
||||
const (
|
||||
// default delimiter
|
||||
defaultDelimiter byte = '.'
|
||||
// default struct tag name for binding data to struct
|
||||
defaultStructTag = "mapstructure"
|
||||
// struct tag name for set default-value on binding data
|
||||
defaultValueTag = "default"
|
||||
)
|
||||
|
||||
// internal vars
|
||||
// type intArr []int
|
||||
type strArr []string
|
||||
|
||||
// type intMap map[string]int
|
||||
type strMap map[string]string
|
||||
|
||||
// This is a default config manager instance
|
||||
var dc = New("default")
|
||||
|
||||
// Config structure definition
|
||||
type Config struct {
|
||||
// save the latest error, will clear after read.
|
||||
err error
|
||||
// config instance name
|
||||
name string
|
||||
lock sync.RWMutex
|
||||
|
||||
// config options
|
||||
opts *Options
|
||||
// all config data
|
||||
data map[string]any
|
||||
|
||||
// loaded config files records
|
||||
loadedUrls []string
|
||||
loadedFiles []string
|
||||
driverNames []string
|
||||
// driver alias to name map.
|
||||
aliasMap map[string]string
|
||||
reloading bool
|
||||
|
||||
// TODO Deprecated decoder and encoder, use driver instead
|
||||
// drivers map[string]Driver
|
||||
|
||||
// decoders["toml"] = func(blob []byte, v any) (err error){}
|
||||
// decoders["yaml"] = func(blob []byte, v any) (err error){}
|
||||
decoders map[string]Decoder
|
||||
encoders map[string]Encoder
|
||||
|
||||
// cache on got config data
|
||||
intCache map[string]int
|
||||
strCache map[string]string
|
||||
// iArrCache map[string]intArr TODO cache it
|
||||
// iMapCache map[string]intMap
|
||||
sArrCache map[string]strArr
|
||||
sMapCache map[string]strMap
|
||||
}
|
||||
|
||||
// New config instance with custom options, default with JSON driver
|
||||
func New(name string, opts ...OptionFn) *Config {
|
||||
return NewEmpty(name, opts...).WithDriver(JSONDriver)
|
||||
}
|
||||
|
||||
// NewGeneric create generic config instance with custom options.
|
||||
//
|
||||
// - default add options: ParseEnv, ParseDefault, ParseTime
|
||||
func NewGeneric(name string, opts ...OptionFn) *Config {
|
||||
return NewEmpty(name, ParseEnv, ParseDefault, ParseTime).WithOptions(opts...).WithDriver(JSONDriver)
|
||||
}
|
||||
|
||||
// NewEmpty create config instance with custom options
|
||||
func NewEmpty(name string, opts ...OptionFn) *Config {
|
||||
c := &Config{
|
||||
name: name,
|
||||
opts: newDefaultOption(),
|
||||
data: make(map[string]any),
|
||||
// don't add any drivers
|
||||
encoders: map[string]Encoder{},
|
||||
decoders: map[string]Decoder{},
|
||||
aliasMap: make(map[string]string),
|
||||
}
|
||||
|
||||
return c.WithOptions(opts...)
|
||||
}
|
||||
|
||||
// NewWith create config instance, and you can call some init func
|
||||
func NewWith(name string, fn func(c *Config)) *Config {
|
||||
return New(name).With(fn)
|
||||
}
|
||||
|
||||
// NewWithOptions config instance. alias of New()
|
||||
func NewWithOptions(name string, opts ...OptionFn) *Config {
|
||||
return New(name).WithOptions(opts...)
|
||||
}
|
||||
|
||||
// Default get the default instance
|
||||
func Default() *Config { return dc }
|
||||
|
||||
/*************************************************************
|
||||
* config drivers
|
||||
*************************************************************/
|
||||
|
||||
// WithDriver set multi drivers at once.
|
||||
func WithDriver(drivers ...Driver) { dc.WithDriver(drivers...) }
|
||||
|
||||
// WithDriver set multi drivers at once.
|
||||
func (c *Config) WithDriver(drivers ...Driver) *Config {
|
||||
for _, driver := range drivers {
|
||||
c.AddDriver(driver)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// AddDriver set a decoder and encoder driver for a format.
|
||||
func AddDriver(driver Driver) { dc.AddDriver(driver) }
|
||||
|
||||
// AddDriver set a decoder and encoder driver for a format.
|
||||
func (c *Config) AddDriver(driver Driver) {
|
||||
format := driver.Name()
|
||||
if len(driver.Aliases()) > 0 {
|
||||
for _, alias := range driver.Aliases() {
|
||||
c.aliasMap[alias] = format
|
||||
}
|
||||
}
|
||||
|
||||
c.driverNames = append(c.driverNames, format)
|
||||
c.decoders[format] = driver.GetDecoder()
|
||||
c.encoders[format] = driver.GetEncoder()
|
||||
}
|
||||
|
||||
// HasDecoder has decoder
|
||||
func (c *Config) HasDecoder(format string) bool {
|
||||
format = c.resolveFormat(format)
|
||||
_, ok := c.decoders[format]
|
||||
return ok
|
||||
}
|
||||
|
||||
// HasEncoder has encoder
|
||||
func (c *Config) HasEncoder(format string) bool {
|
||||
format = c.resolveFormat(format)
|
||||
_, ok := c.encoders[format]
|
||||
return ok
|
||||
}
|
||||
|
||||
// DelDriver delete driver of the format
|
||||
func (c *Config) DelDriver(format string) {
|
||||
format = c.resolveFormat(format)
|
||||
delete(c.decoders, format)
|
||||
delete(c.encoders, format)
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* helper methods
|
||||
*************************************************************/
|
||||
|
||||
// Name get config name
|
||||
func (c *Config) Name() string { return c.name }
|
||||
|
||||
// AddAlias add alias for a format(driver name)
|
||||
func AddAlias(format, alias string) { dc.AddAlias(format, alias) }
|
||||
|
||||
// AddAlias add alias for a format(driver name)
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// config.AddAlias("ini", "conf")
|
||||
func (c *Config) AddAlias(format, alias string) {
|
||||
c.aliasMap[alias] = format
|
||||
}
|
||||
|
||||
// AliasMap get alias map
|
||||
func (c *Config) AliasMap() map[string]string { return c.aliasMap }
|
||||
|
||||
// Error get last error, will clear after read.
|
||||
func (c *Config) Error() error {
|
||||
err := c.err
|
||||
c.err = nil
|
||||
return err
|
||||
}
|
||||
|
||||
// IsEmpty of the config
|
||||
func (c *Config) IsEmpty() bool {
|
||||
return len(c.data) == 0
|
||||
}
|
||||
|
||||
// LoadedUrls get loaded urls list
|
||||
func (c *Config) LoadedUrls() []string { return c.loadedUrls }
|
||||
|
||||
// LoadedFiles get loaded files name
|
||||
func (c *Config) LoadedFiles() []string { return c.loadedFiles }
|
||||
|
||||
// DriverNames get loaded driver names
|
||||
func (c *Config) DriverNames() []string { return c.driverNames }
|
||||
|
||||
// Reset data and caches
|
||||
func Reset() { dc.ClearAll() }
|
||||
|
||||
// ClearAll data and caches
|
||||
func ClearAll() { dc.ClearAll() }
|
||||
|
||||
// ClearAll data and caches
|
||||
func (c *Config) ClearAll() {
|
||||
c.ClearData()
|
||||
c.ClearCaches()
|
||||
|
||||
c.aliasMap = make(map[string]string)
|
||||
// options
|
||||
c.opts.Readonly = false
|
||||
}
|
||||
|
||||
// ClearData clear data
|
||||
func (c *Config) ClearData() {
|
||||
c.fireHook(OnCleanData)
|
||||
|
||||
c.data = make(map[string]any)
|
||||
c.loadedUrls = []string{}
|
||||
c.loadedFiles = []string{}
|
||||
}
|
||||
|
||||
// ClearCaches clear caches
|
||||
func (c *Config) ClearCaches() {
|
||||
if c.opts.EnableCache {
|
||||
c.intCache = nil
|
||||
c.strCache = nil
|
||||
c.sMapCache = nil
|
||||
c.sArrCache = nil
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* helper methods
|
||||
*************************************************************/
|
||||
|
||||
// fire hook
|
||||
func (c *Config) fireHook(name string) {
|
||||
if c.opts.HookFunc != nil {
|
||||
c.opts.HookFunc(name, c)
|
||||
}
|
||||
}
|
||||
|
||||
// record error
|
||||
func (c *Config) addError(err error) {
|
||||
c.err = err
|
||||
}
|
||||
|
||||
// format and record error
|
||||
func (c *Config) addErrorf(format string, a ...any) {
|
||||
c.err = fmt.Errorf(format, a...)
|
||||
}
|
||||
Reference in New Issue
Block a user