diff --git a/viper.go b/viper.go index bdfa5aa..81bee79 100644 --- a/viper.go +++ b/viper.go @@ -14,6 +14,7 @@ import ( "os" "path" "path/filepath" + "strings" "time" "github.com/BurntSushi/toml" @@ -75,19 +76,24 @@ func GetTime(key string) time.Time { return cast.ToTime(Get(key)) } -func GetStringArray(key string) []string { - return cast.ToStringArray(Get(key)) +func GetStringSlice(key string) []string { + return cast.ToStringSlice(Get(key)) +} + +func GetStringMap(key string) map[string]interface{} { + return cast.ToStringMap(Get(key)) +} + +func GetStringMapString(key string) map[string]string { + return cast.ToStringMapString(Get(key)) } func find(key string) interface{} { var val interface{} var exists bool - // If the requested key is an alias, then return the proper key - newkey, exists := aliases[key] - if exists { - return find(newkey) - } + // if the requested key is an alias, then return the proper key + key = realKey(key) val, exists = override[key] if exists { @@ -111,6 +117,7 @@ func find(key string) interface{} { } func Get(key string) interface{} { + key = strings.ToLower(key) v := find(key) if v == nil { @@ -140,32 +147,50 @@ func IsSet(key string) bool { } func RegisterAlias(alias string, key string) { - aliases[alias] = key + registerAlias(alias, strings.ToLower(key)) +} + +func registerAlias(alias string, key string) { + alias = strings.ToLower(alias) + if alias != key && alias != realKey(key) { + _, exists := aliases[alias] + if !exists { + aliases[alias] = key + } + } else { + jww.WARN.Println("Creating circular reference alias", alias, key, realKey(key)) + } +} + +func realKey(key string) string { + newkey, exists := aliases[key] + if exists { + jww.DEBUG.Println("Alias", key, "to", newkey) + return realKey(newkey) + } else { + return key + } } func InConfig(key string) bool { + // if the requested key is an alias, then return the proper key + key = realKey(key) + _, exists := config[key] return exists } func SetDefault(key string, value interface{}) { // If alias passed in, then set the proper default - newkey, exists := aliases[key] - if exists { - defaults[newkey] = value - } else { - defaults[key] = value - } + key = realKey(strings.ToLower(key)) + defaults[key] = value } func Set(key string, value interface{}) { // If alias passed in, then set the proper override - newkey, exists := aliases[key] - if exists { - override[newkey] = value - } else { - override[key] = value - } + key = realKey(strings.ToLower(key)) + key = strings.ToLower(key) + override[key] = value } func ReadInConfig() { @@ -200,6 +225,16 @@ func MarshallReader(in io.Reader) { jww.ERROR.Fatalf("Error parsing config: %s", err) } } + + insensativiseMap() +} + +func insensativiseMap() { + for key, _ := range config { + if key != strings.ToLower(key) { + registerAlias(key, key) + } + } } func SetConfigName(in string) { diff --git a/viper_test.go b/viper_test.go index 1a4b624..1aba562 100644 --- a/viper_test.go +++ b/viper_test.go @@ -25,7 +25,7 @@ title = "TOML Example" [owner] organization = "MongoDB" -bio = "MongoDB Chief Developer Advocate & Hacker at Large" +Bio = "MongoDB Chief Developer Advocate & Hacker at Large" dob = 1979-05-27T07:32:00Z # First class dates? Why not?`) var jsonExample = []byte(`{ @@ -114,6 +114,19 @@ func TestTOML(t *testing.T) { assert.Equal(t, "TOML Example", Get("title")) } -func TestCaseSensitive(t *testing.T) { - assert.Equal(t, true, Get("Hacker")) +func TestCaseInSensitive(t *testing.T) { + assert.Equal(t, true, Get("hacker")) + Set("Title", "Checking Case") + assert.Equal(t, "Checking Case", Get("tItle")) +} + +func TestAliasesOfAliases(t *testing.T) { + RegisterAlias("Foo", "Bar") + RegisterAlias("Bar", "Title") + assert.Equal(t, "Checking Case", Get("FOO")) +} + +func TestRecursiveAliases(t *testing.T) { + RegisterAlias("Baz", "Roo") + RegisterAlias("Roo", "baz") }