Beispiel #1
0
func Read(ymlFlashMap map[string]interface{}) (FlashMap, error) {
	flashMap := newFlashMap()

	ymlAreas := ymlFlashMap["areas"]
	if ymlAreas == nil {
		return flashMap, util.NewNewtError(
			"\"areas\" mapping missing from flash map definition")
	}

	areaMap := cast.ToStringMap(ymlAreas)
	for k, v := range areaMap {
		if _, ok := flashMap.Areas[k]; ok {
			return flashMap, flashAreaErr(k, "name conflict")
		}

		ymlArea := cast.ToStringMap(v)
		area, err := parseFlashArea(k, ymlArea)
		if err != nil {
			return flashMap, flashAreaErr(k, err.Error())
		}

		flashMap.Areas[k] = area
	}

	flashMap.detectOverlaps()

	return flashMap, nil
}
Beispiel #2
0
func TestFlatMap(t *testing.T) {
	var v interface{}
	var err error

	m := map[string]interface{}{
		".cat":                 "garfield",
		".dog":                 "odie",
		".friends.[0]":         "John",
		".turtle":              "0",
		".birdColors.cardinal": "red",
		".birdColors.blueJay":  "blue",
		".57":         int64(57),
		".doesItWork": true,
	}

	f := NewFlatMap(m)
	assert.Equal(t, f.Contains("cat"), true)
	assert.Equal(t, f.Contains(".cat"), false)
	assert.Equal(t, f.Contains(".birdColors.cardinal"), false)

	f.Delete("birdColors")

	r := map[string]interface{}{
		"cat":        "garfield",
		"dog":        "odie",
		"friends":    []interface{}{"John"},
		"turtle":     "0",
		"57":         int64(57),
		"doesItWork": true,
	}

	v, err = Expand(f.Map, "")
	assert.Equal(t, cast.ToStringMap(v), r)
	assert.Equal(t, err, nil)

	m2 := map[string]interface{}{
		".friends.[0]": "Odie",
		".friends.[1]": "John",
	}

	f2 := NewFlatMap(m2)
	f.Merge(f2)

	r2 := map[string]interface{}{
		"cat":        "garfield",
		"dog":        "odie",
		"friends":    []interface{}{"Odie", "John"},
		"turtle":     "0",
		"57":         int64(57),
		"doesItWork": true,
	}

	v, err = Expand(f.Map, "")

	// FIXME: Buggy because of array order issues
	assert.Equal(t, cast.ToStringMap(v), r2)
	assert.Equal(t, err, nil)
}
Beispiel #3
0
// searchMap recursively searches for a value for path in source map.
// Returns nil if not found.
// Note: This assumes that the path entries and map keys are lower cased.
func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {
	if len(path) == 0 {
		return source
	}

	next, ok := source[path[0]]
	if ok {
		// Fast path
		if len(path) == 1 {
			return next
		}

		// Nested case
		switch next.(type) {
		case map[interface{}]interface{}:
			return v.searchMap(cast.ToStringMap(next), path[1:])
		case map[string]interface{}:
			// Type assertion is safe here since it is only reached
			// if the type of `next` is the same as the type being asserted
			return v.searchMap(next.(map[string]interface{}), path[1:])
		default:
			// got a value but nested key expected, return "nil" for not found
			return nil
		}
	}
	return nil
}
Beispiel #4
0
// flattenAndMergeMap recursively flattens the given map into a map[string]bool
// of key paths (used as a set, easier to manipulate than a []string):
// - each path is merged into a single key string, delimited with v.keyDelim (= ".")
// - if a path is shadowed by an earlier value in the initial shadow map,
//   it is skipped.
// The resulting set of paths is merged to the given shadow set at the same time.
func (v *Viper) flattenAndMergeMap(shadow map[string]bool, m map[string]interface{}, prefix string) map[string]bool {
	if shadow != nil && prefix != "" && shadow[prefix] {
		// prefix is shadowed => nothing more to flatten
		return shadow
	}
	if shadow == nil {
		shadow = make(map[string]bool)
	}

	var m2 map[string]interface{}
	if prefix != "" {
		prefix += v.keyDelim
	}
	for k, val := range m {
		fullKey := prefix + k
		switch val.(type) {
		case map[string]interface{}:
			m2 = val.(map[string]interface{})
		case map[interface{}]interface{}:
			m2 = cast.ToStringMap(val)
		default:
			// immediate value
			shadow[strings.ToLower(fullKey)] = true
			continue
		}
		// recursively merge to shadow map
		shadow = v.flattenAndMergeMap(shadow, m2, fullKey)
	}
	return shadow
}
Beispiel #5
0
// mergeFlatMap merges the given maps, excluding values of the second map
// shadowed by values from the first map.
func (v *Viper) mergeFlatMap(shadow map[string]bool, mi interface{}) map[string]bool {
	// unify input map
	var m map[string]interface{}
	switch mi.(type) {
	case map[string]string, map[string]FlagValue:
		m = cast.ToStringMap(mi)
	default:
		return shadow
	}

	// scan keys
outer:
	for k, _ := range m {
		path := strings.Split(k, v.keyDelim)
		// scan intermediate paths
		var parentKey string
		for i := 1; i < len(path); i++ {
			parentKey = strings.Join(path[0:i], v.keyDelim)
			if shadow[parentKey] {
				// path is shadowed, continue
				continue outer
			}
		}
		// add key
		shadow[strings.ToLower(k)] = true
	}
	return shadow
}
Beispiel #6
0
func (p *Page) getRenderingConfig() *helpers.Blackfriday {

	p.renderingConfigInit.Do(func() {
		pageParam := p.GetParam("blackfriday")
		siteParam := viper.GetStringMap("blackfriday")

		combinedParam := siteParam

		if pageParam != nil {
			combinedParam = make(map[string]interface{})

			for k, v := range siteParam {
				combinedParam[k] = v
			}

			pageConfig := cast.ToStringMap(pageParam)

			for key, value := range pageConfig {
				combinedParam[key] = value
			}
		}
		p.renderingConfig = helpers.NewBlackfriday()
		if err := mapstructure.Decode(combinedParam, p.renderingConfig); err != nil {
			jww.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
		}
	})

	return p.renderingConfig
}
Beispiel #7
0
// Get can retrieve any value given the key to use
// Get returns an interface. For a specific value use one of the Get____ methods.
func (c RawConfig) Get(key string) interface{} {
	path := strings.Split(key, keyDelim)

	val := c.find(strings.ToLower(key))

	if val == nil {
		source := c.find(path[0])
		if source == nil {
			return nil
		}

		if reflect.TypeOf(source).Kind() == reflect.Map {
			val = c.searchMap(cast.ToStringMap(source), path[1:])
		}
	}

	switch val.(type) {
	case bool:
		return cast.ToBool(val)
	case string:
		return cast.ToString(val)
	case int64, int32, int16, int8, int:
		return cast.ToInt(val)
	case float64, float32:
		return cast.ToFloat64(val)
	case time.Time:
		return cast.ToTime(val)
	case time.Duration:
		return cast.ToDuration(val)
	case []string:
		return val
	}
	return val
}
Beispiel #8
0
func TestDifferentFrontMatterVarTypes(t *testing.T) {
	page, _ := NewPage("test/file1.md")
	_, _ = page.ReadFrom(strings.NewReader(PAGE_WITH_VARIOUS_FRONTMATTER_TYPES))

	dateval, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
	if page.GetParam("a_string") != "bar" {
		t.Errorf("frontmatter not handling strings correctly should be %s, got: %s", "bar", page.GetParam("a_string"))
	}
	if page.GetParam("an_integer") != 1 {
		t.Errorf("frontmatter not handling ints correctly should be %s, got: %s", "1", page.GetParam("an_integer"))
	}
	if page.GetParam("a_float") != 1.3 {
		t.Errorf("frontmatter not handling floats correctly should be %f, got: %s", 1.3, page.GetParam("a_float"))
	}
	if page.GetParam("a_bool") != false {
		t.Errorf("frontmatter not handling bools correctly should be %t, got: %s", false, page.GetParam("a_bool"))
	}
	if page.GetParam("a_date") != dateval {
		t.Errorf("frontmatter not handling dates correctly should be %s, got: %s", dateval, page.GetParam("a_date"))
	}
	param := page.GetParam("a_table")
	if param == nil {
		t.Errorf("frontmatter not handling tables correctly should be type of %v, got: type of %v", reflect.TypeOf(page.Params["a_table"]), reflect.TypeOf(param))
	}
	if cast.ToStringMap(param)["a_key"] != "a_value" {
		t.Errorf("frontmatter not handling values inside a table correctly should be %s, got: %s", "a_value", cast.ToStringMap(page.Params["a_table"])["a_key"])
	}
}
Beispiel #9
0
// NewBlackfriday creates a new Blackfriday filled with site config or some sane defaults.
func NewBlackfriday() *Blackfriday {
	combinedParam := map[string]interface{}{
		"smartypants":                      true,
		"angledQuotes":                     false,
		"fractions":                        true,
		"hrefTargetBlank":                  false,
		"smartDashes":                      true,
		"latexDashes":                      true,
		"plainIDAnchors":                   true,
		"sourceRelativeLinks":              false,
		"sourceRelativeLinksProjectFolder": "/docs/content",
	}

	siteParam := viper.GetStringMap("blackfriday")
	if siteParam != nil {
		siteConfig := cast.ToStringMap(siteParam)

		for key, value := range siteConfig {
			combinedParam[key] = value
		}
	}

	combinedConfig := &Blackfriday{}
	if err := mapstructure.Decode(combinedParam, combinedConfig); err != nil {
		jww.FATAL.Printf("Failed to get site rendering config\n%s", err.Error())
	}

	return combinedConfig
}
Beispiel #10
0
func TestMapMap(t *testing.T) {
	var v interface{}
	var processingErrors []error
	var err error

	m := map[string]interface{}{
		"cat":        "garfield",
		"dog":        "odie",
		"friends":    []interface{}{"John"},
		"turtle":     "0",
		"57":         int64(57),
		"doesItWork": true,
	}

	r := map[string]interface{}{
		"cat":          "garfield",
		"frog":         "0",
		"myOnlyFriend": "John",
	}

	var mappers []*Mapper
	mappers = append(mappers, NewMapper("cat", "cat"))
	mappers = append(mappers, NewMapper("turtle", "frog"))
	mappers = append(mappers, NewMapper("friends.[0]", "myOnlyFriend"))

	v, processingErrors, err = MapIt(m, mappers)

	assert.Equal(t, cast.ToStringMap(v), r)
	assert.Equal(t, processingErrors, []error{})
	assert.Equal(t, len(processingErrors), 0)
	assert.Equal(t, err, nil)
}
Beispiel #11
0
func (v *Viper) searchMap(source map[string]interface{}, path []string) interface{} {

	if len(path) == 0 {
		return source
	}

	var ok bool
	var next interface{}
	for k, v := range source {
		if strings.ToLower(k) == strings.ToLower(path[0]) {
			ok = true
			next = v
			break
		}
	}

	if ok {
		switch next.(type) {
		case map[interface{}]interface{}:
			return v.searchMap(cast.ToStringMap(next), path[1:])
		case map[string]interface{}:
			// Type assertion is safe here since it is only reached
			// if the type of `next` is the same as the type being asserted
			return v.searchMap(next.(map[string]interface{}), path[1:])
		default:
			return next
		}
	} else {
		return nil
	}
}
Beispiel #12
0
// Updates our lookup table of insensitive materialized paths to their
// corresponding 'real' keys. E.g.
//
//		Database.Connections.Hosts <- database.connections.hosts
//
// By maintaining a separate index and maintaining case in the original
// stringmaps (e.g. by lowercasing keys directly) we accomodate the passing
// of config data to structures that ~may~ be case sensitive. I.E we avoid
// destructive operations on configurationd data.
func (self *ConfigSource) updateIndex(key string, data interface{}) {
	if data == nil {
		return
	}

	// Don't change the case of the original key if it already exists.
	_, index_exists := self.index[strings.ToLower(key)]
	if index_exists == false {
		self.index[strings.ToLower(key)] = key
	}

	if reflect.TypeOf(data).Kind() != reflect.Map {
		return
	}

	for child_key, val := range cast.ToStringMap(data) {
		var joined_key string
		if len(key) > 0 {
			joined_key = key + "." + child_key
		} else {
			joined_key = child_key
		}
		self.updateIndex(joined_key, val)
	}
}
Beispiel #13
0
// Merges data into the our attributes configuration tier from a struct.
func (manager *Config) MergeAttributes(val interface{}) error {
	merged_config := maps.Merge(
		manager.attributes.ToStringMap(),
		cast.ToStringMap(val),
	)

	manager.attributes.FromStringMap(merged_config)
	return nil
}
Beispiel #14
0
func (v *Viper) Sub(key string) *Viper {
	subv := New()
	data := v.Get(key)
	if reflect.TypeOf(data).Kind() == reflect.Map {
		subv.config = cast.ToStringMap(data)
		return subv
	}
	return nil
}
Beispiel #15
0
// toCaseInsensitiveValue checks if the value is a  map;
// if so, create a copy and lower-case the keys recursively.
func toCaseInsensitiveValue(value interface{}) interface{} {
	switch v := value.(type) {
	case map[interface{}]interface{}:
		value = copyAndInsensitiviseMap(cast.ToStringMap(v))
	case map[string]interface{}:
		value = copyAndInsensitiviseMap(v)
	}

	return value
}
Beispiel #16
0
func (p *Page) getRenderingConfig() *helpers.Blackfriday {

	p.renderingConfigInit.Do(func() {
		pageParam := cast.ToStringMap(p.GetParam("blackfriday"))

		p.renderingConfig = helpers.NewBlackfriday()
		if err := mapstructure.Decode(pageParam, p.renderingConfig); err != nil {
			jww.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
		}
	})

	return p.renderingConfig
}
Beispiel #17
0
func insensitiviseMap(m map[string]interface{}) {
	for key, val := range m {
		lower := strings.ToLower(key)
		if key != lower {
			delete(m, key)
			m[lower] = val
		}

		if val != nil && reflect.TypeOf(val).Kind() == reflect.Map {
			insensitiviseMap(cast.ToStringMap(val))
		}
	}
}
Beispiel #18
0
func (v *Viper) Get(key string) interface{} {
	path := strings.Split(key, v.keyDelim)

	var val interface{}
	lcaseKey := strings.ToLower(key)
	source := v.find(path[0])
	if source != nil {
		if reflect.TypeOf(source).Kind() == reflect.Map {
			val = v.searchMap(cast.ToStringMap(source), path[1:])
		}
	}

	if val == nil {
		val = v.find(lcaseKey)
	}

	if val == nil {
		return nil
	}

	var valType interface{}
	if !v.typeByDefValue {
		valType = val
	} else {
		defVal, defExists := v.defaults[lcaseKey]
		if defExists {
			valType = defVal
		} else {
			valType = val
		}
	}

	switch valType.(type) {
	case bool:
		return cast.ToBool(val)
	case string:
		return cast.ToString(val)
	case int64, int32, int16, int8, int:
		return cast.ToInt(val)
	case float64, float32:
		return cast.ToFloat64(val)
	case time.Time:
		return cast.ToTime(val)
	case time.Duration:
		return cast.ToDuration(val)
	case []string:
		return cast.ToStringSlice(val)
	}
	return val
}
Beispiel #19
0
func (c *Configr) mergeMap(key string, value interface{}, targetMap map[string]interface{}) map[string]interface{} {
	if reflect.TypeOf(value).Kind() == reflect.Map {
		targetMap = c.traverseSubMap(key, cast.ToStringMap(value), targetMap)
	} else {
		path := strings.SplitN(key, c.keyDelimeter, 2)
		if len(path) == 2 {
			targetMap = c.traverseKeyPath(path[0], path[1], value, targetMap)
		} else {
			targetMap[key] = value
		}
	}

	return targetMap
}
func GetStringMapFeatures(v *viper.Viper, features map[string]bool,
	key string) map[string]interface{} {

	result := map[string]interface{}{}

	slice := GetSliceFeatures(v, features, key)
	for _, itf := range slice {
		sub := cast.ToStringMap(itf)
		for k, v := range sub {
			result[k] = v
		}
	}

	return result
}
Beispiel #21
0
// Generic functional, recursive stringmap traversal.
// Provides the callback with the current value, materialized path, and depth.
func traverse(data map[string]interface{}, path string, depth int, cb Traverser) {
	for key, val := range data {
		var joined_key string
		if len(path) > 0 {
			joined_key = path + "." + key
		} else {
			joined_key = key
		}

		if cb(joined_key, val, depth) {
			if val != nil && reflect.TypeOf(val).Kind() == reflect.Map {
				traverse(cast.ToStringMap(val), joined_key, depth+1, cb)
			}
		}
	}
}
Beispiel #22
0
func (c *Configr) findKeysAndValuesToValidate(key string, value interface{}) (map[string]interface{}, error) {
	keysAndValues := make(map[string]interface{})
	if reflect.TypeOf(value).Kind() == reflect.Map {
		for validatorKey := range c.valueValidators {
			if !strings.HasPrefix(validatorKey, key) {
				continue
			}
			valueToValidate := searchMap(cast.ToStringMap(value), strings.Split(validatorKey, c.keyDelimeter)[1:])
			keysAndValues[validatorKey] = valueToValidate
		}
	} else {
		keysAndValues[key] = value
	}

	return keysAndValues, nil
}
Beispiel #23
0
func (suite *GitConfigTestSuite) TestCast() {
	assert := assert.New(suite.T())
	hostsRaw := viper.Get("git.hosts")
	//fmt.Println(hostsRaw)
	hostsSlice := cast.ToSlice(hostsRaw)
	//fmt.Println(hostsSlice)

	for _, host := range hostsSlice {
		hostMap := cast.ToStringMap(host)
		name := cast.ToString(hostMap["name"])
		https := cast.ToBool(hostMap["https"])
		if name == "git.saber.io" {
			assert.Equal(false, https)
		}
	}
}
Beispiel #24
0
// copyAndInsensitiviseMap behaves like insensitiviseMap, but creates a copy of
// any map it makes case insensitive.
func copyAndInsensitiviseMap(m map[string]interface{}) map[string]interface{} {
	nm := make(map[string]interface{})

	for key, val := range m {
		lkey := strings.ToLower(key)
		switch v := val.(type) {
		case map[interface{}]interface{}:
			nm[lkey] = copyAndInsensitiviseMap(cast.ToStringMap(v))
		case map[string]interface{}:
			nm[lkey] = copyAndInsensitiviseMap(v)
		default:
			nm[lkey] = v
		}
	}

	return nm
}
Beispiel #25
0
func (v *Viper) IsSet(key string) bool {
	path := strings.Split(key, v.keyDelim)

	lcaseKey := strings.ToLower(key)
	val := v.find(lcaseKey)

	if val == nil {
		source := v.find(strings.ToLower(path[0]))
		if source != nil {
			if reflect.TypeOf(source).Kind() == reflect.Map {
				val = v.searchMap(cast.ToStringMap(source), path[1:])
			}
		}
	}

	return val != nil
}
Beispiel #26
0
func (p *Page) getRenderingConfig() *helpers.Blackfriday {

	p.renderingConfigInit.Do(func() {
		pageParam := cast.ToStringMap(p.GetParam("blackfriday"))
		if p.Language() == nil {
			panic(fmt.Sprintf("nil language for %s with source lang %s", p.BaseFileName(), p.lang))
		}
		p.renderingConfig = helpers.NewBlackfriday(p.Language())

		if err := mapstructure.Decode(pageParam, p.renderingConfig); err != nil {
			jww.FATAL.Printf("Failed to get rendering config for %s:\n%s", p.BaseFileName(), err.Error())
		}

	})

	return p.renderingConfig
}
Beispiel #27
0
func (c *Config) expandKeysValues(vd map[string]interface{}, kkl string) {
	defMap := make(map[string]interface{})
	kl := ""
	for k, v := range vd {
		if kkl != "" {
			kl = kkl + "." + k
		} else {
			kl = k
		}
		if reflect.TypeOf(v) == reflect.TypeOf(defMap) {
			c.expandKeysValues(cast.ToStringMap(v), kl)
		} else {
			var val interface{} = v
			c.configValues[kl] = val
		}
	}
}
Beispiel #28
0
// Loads and sequentially + recursively merges the provided config arguments. Returns
// an error if any of the files fail to load, though this may be expecte
// in the case of search paths.
func (manager *Config) ReadPaths(paths ...string) error {
	var err error
	var loaded interface{}

	merged_config := manager.attributes.ToStringMap()
	errs := []error{}

	for _, base_path := range paths {
		var final_path string

		if filepath.IsAbs(base_path) == false {
			final_path = path.Join(manager.rootPath, base_path)
		} else {
			final_path = path.Join(manager.rootPath, base_path)
		}

		loaded, err = reader.ReadFile(final_path)

		if err != nil {
			errs = append(errs, err)
			continue
		}

		// In-place recursive coercion to stringmap.
		coerced := cast.ToStringMap(loaded)
		maps.ToStringMapRecursive(coerced)

		if merged_config == nil {
			merged_config = coerced
		} else {
			merged_config = maps.Merge(
				merged_config,
				coerced,
			)
		}

		manager.attributes.FromStringMap(merged_config)
	}

	if len(errs) > 0 {
		return &errors.LoadError{Errors: errs}
	} else {
		return nil
	}
}
Beispiel #29
0
func (c *Config) searchMap(s map[string]interface{}, p []string) interface{} {
	if len(p) == 0 {
		return s
	}

	if next, ok := s[p[0]]; ok {
		switch next.(type) {
		case map[interface{}]interface{}:
			return c.searchMap(cast.ToStringMap(next), p[1:])
		case map[string]interface{}:
			return c.searchMap(next.(map[string]interface{}), p[1:])
		default:
			return next
		}
	} else {
		return nil
	}
}
Beispiel #30
0
// ToLowerMap makes all the keys in the given map lower cased and will do so
// recursively.
// Notes:
// * This will modify the map given.
// * Any nested map[interface{}]interface{} will be converted to map[string]interface{}.
func ToLowerMap(m map[string]interface{}) {
	for k, v := range m {
		switch v.(type) {
		case map[interface{}]interface{}:
			v = cast.ToStringMap(v)
			ToLowerMap(v.(map[string]interface{}))
		case map[string]interface{}:
			ToLowerMap(v.(map[string]interface{}))
		}

		lKey := strings.ToLower(k)
		if k != lKey {
			delete(m, k)
			m[lKey] = v
		}

	}
}