func tryTConfig(value reflect.Value) (reflect.Value, bool) {
	v := chaseValue(value)
	t := v.Type()
	if t == tConfig {
		v := pointerize(tConfigPtr, tConfig, v)
		return v.Elem(), true
	}
	if !t.ConvertibleTo(tConfig) {
		return reflect.Value{}, false
	}
	v = pointerize(reflect.PtrTo(v.Type()), v.Type(), v)
	if !v.Type().ConvertibleTo(tConfigPtr) {
		return reflect.Value{}, false
	}
	v = v.Convert(tConfigPtr)
	return v.Elem(), true
}
tryTConfig tries to convert input value into addressable Config by converting
to *Config first. If value is convertible to Config, but not addressable a new
value is allocated in order to guarantee returned value of type Config is
addressable. Returns false if type value is not convertible to TConfig.
package ucfg
import (
	"reflect"
	"strings"
)
type tagOptions struct {
	squash bool
}
var noTagOpts = tagOptions{}
func parseTags(tag string) (string, tagOptions) {
	s := strings.Split(tag, ",")
	opts := tagOptions{}
	for _, opt := range s[1:] {
		switch opt {
		case "squash", "inline":
			opts.squash = true
		}
	}
	return s[0], opts
}
func fieldName(tagName, structName string) string {
	if tagName != "" {
		return tagName
	}
	return strings.ToLower(structName)
}
func chaseValueInterfaces(v reflect.Value) reflect.Value {
	for v.Kind() == reflect.Interface && !v.IsNil() {
		v = v.Elem()
	}
	return v
}
func chaseValuePointers(v reflect.Value) reflect.Value {
	for v.Kind() == reflect.Ptr && !v.IsNil() {
		v = v.Elem()
	}
	return v
}
func chaseValue(v reflect.Value) reflect.Value {
	for (v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface) && !v.IsNil() {
		v = v.Elem()
	}
	return v
}
func chaseTypePointers(t reflect.Type) reflect.Type {
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	return t
}