diff --git a/datatype.go b/datatype.go index 6933880..687d235 100644 --- a/datatype.go +++ b/datatype.go @@ -22,7 +22,6 @@ type cValue struct { durval time.Duration boolval bool strval string - mapval map[string]cValue err error } diff --git a/envconf.go b/envconf.go index 4697c83..d5ad713 100644 --- a/envconf.go +++ b/envconf.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "os" + "regexp" "strings" "time" "unicode" @@ -38,26 +39,22 @@ func NewConfig() *Config { splitted := strings.SplitN(v, "=", 2) if len(splitted) == 2 { key := cleanKey(splitted[0]) - keysplit := strings.Split(key, "_") - left := "" - right := "" - - if len(keysplit) > 1 { - left = strings.Join(keysplit[:len(keysplit)-1], "_") - right = keysplit[len(keysplit)-1] - } + left, right, mappable := keySplit(key) if unicode.IsLetter(getFirstRune(key)) { - if len(config.mapEnv[left]) == 0 { - config.mapEnv[left] = make(map[string]cEntry) - } var entry cEntry entry.value = splitted[1] entry.dtype = TypeNone entry.unset = false entry.empty = false config.env[key] = entry - config.mapEnv[left][right] = entry + if mappable { + if len(config.mapEnv[left]) == 0 { + config.mapEnv[left] = make(map[string]cEntry) + } + + config.mapEnv[left][right] = entry + } } } } @@ -67,17 +64,17 @@ func NewConfig() *Config { // Define the type of an environment variable. // Variables without a defined type will be ignored by Parse. func (c *Config) Define(key string, dtype DataType) { - upper := strings.ToUpper(key) - entry, ok := c.env[upper] + key = cleanKey(key) + entry, ok := c.env[key] if ok { entry.dtype = dtype - c.env[upper] = entry + c.env[key] = entry } else { var entry cEntry entry.dtype = dtype entry.unset = true entry.empty = true - c.env[upper] = entry + c.env[key] = entry } } @@ -97,8 +94,8 @@ func (c *Config) DefineMap(key string, dtype DataType) { // Define the type and default value of an environment variable. // Variables without a defined type will be ignored by Parse. func (c *Config) DefineDefault(key string, val string, dtype DataType) { - upper := strings.ToUpper(key) - entry, ok := c.env[upper] + key = cleanKey(key) + entry, ok := c.env[key] if ok { if entry.unset { entry.value = val @@ -107,7 +104,7 @@ func (c *Config) DefineDefault(key string, val string, dtype DataType) { entry.empty = false entry.defval = val entry.hasdef = true - c.env[upper] = entry + c.env[key] = entry } else { var entry cEntry entry.dtype = dtype @@ -116,7 +113,7 @@ func (c *Config) DefineDefault(key string, val string, dtype DataType) { entry.value = val entry.defval = val entry.hasdef = true - c.env[upper] = entry + c.env[key] = entry } } @@ -261,7 +258,8 @@ func (c *Config) Status() (ok bool) { return } -func cleanKey(str string) string { +func cleanKey(key string) string { + expr := regexp.MustCompile("_+") fn := func(r rune) rune { if (r >= '0' && r <= '9') || (r >= 'A' && r <= 'Z') || r == '_' { return r @@ -269,24 +267,25 @@ func cleanKey(str string) string { return -1 } - str = strings.Map(fn, strings.ToUpper(str)) + key = strings.Map(fn, strings.ToUpper(key)) + return expr.ReplaceAllString(key, "_") +} - oldlen := len(str) + 1 - newlen := len(str) - for newlen < oldlen { - oldlen = newlen - str = strings.ReplaceAll(str, "__", "_") - newlen = len(str) +func keySplit(key string) (left string, right string, ok bool) { + key = cleanKey(key) + pos := strings.LastIndex(key, "_") + ok = false + if (pos+1 < len(key)) && (pos > 1) { + return cleanKey(key[:pos]), cleanKey(key[pos:]), true } - - return str + return } func (c *Config) getRaw(key string, dtype DataType) (val cValue) { val.dtype = TypeNone if c.parsed { - upper := strings.ToUpper(key) - entry, ok := c.env[upper] + key = cleanKey(key) + entry, ok := c.env[key] if ok && (entry.dtype == dtype) { return entry.parsed }