mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	* Update makefile to use dep * Migrate to dep * Fix some deps * Try to find a better version for golang.org/x/net * Try to find a better version for golang.org/x/oauth2
		
			
				
	
	
		
			603 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			603 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2013 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package cldr
 | 
						|
 | 
						|
// This file implements the various inheritance constructs defined by LDML.
 | 
						|
// See http://www.unicode.org/reports/tr35/#Inheritance_and_Validity
 | 
						|
// for more details.
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"log"
 | 
						|
	"reflect"
 | 
						|
	"regexp"
 | 
						|
	"sort"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// fieldIter iterates over fields in a struct. It includes
 | 
						|
// fields of embedded structs.
 | 
						|
type fieldIter struct {
 | 
						|
	v        reflect.Value
 | 
						|
	index, n []int
 | 
						|
}
 | 
						|
 | 
						|
func iter(v reflect.Value) fieldIter {
 | 
						|
	if v.Kind() != reflect.Struct {
 | 
						|
		log.Panicf("value %v must be a struct", v)
 | 
						|
	}
 | 
						|
	i := fieldIter{
 | 
						|
		v:     v,
 | 
						|
		index: []int{0},
 | 
						|
		n:     []int{v.NumField()},
 | 
						|
	}
 | 
						|
	i.descent()
 | 
						|
	return i
 | 
						|
}
 | 
						|
 | 
						|
func (i *fieldIter) descent() {
 | 
						|
	for f := i.field(); f.Anonymous && f.Type.NumField() > 0; f = i.field() {
 | 
						|
		i.index = append(i.index, 0)
 | 
						|
		i.n = append(i.n, f.Type.NumField())
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (i *fieldIter) done() bool {
 | 
						|
	return len(i.index) == 1 && i.index[0] >= i.n[0]
 | 
						|
}
 | 
						|
 | 
						|
func skip(f reflect.StructField) bool {
 | 
						|
	return !f.Anonymous && (f.Name[0] < 'A' || f.Name[0] > 'Z')
 | 
						|
}
 | 
						|
 | 
						|
func (i *fieldIter) next() {
 | 
						|
	for {
 | 
						|
		k := len(i.index) - 1
 | 
						|
		i.index[k]++
 | 
						|
		if i.index[k] < i.n[k] {
 | 
						|
			if !skip(i.field()) {
 | 
						|
				break
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			if k == 0 {
 | 
						|
				return
 | 
						|
			}
 | 
						|
			i.index = i.index[:k]
 | 
						|
			i.n = i.n[:k]
 | 
						|
		}
 | 
						|
	}
 | 
						|
	i.descent()
 | 
						|
}
 | 
						|
 | 
						|
func (i *fieldIter) value() reflect.Value {
 | 
						|
	return i.v.FieldByIndex(i.index)
 | 
						|
}
 | 
						|
 | 
						|
func (i *fieldIter) field() reflect.StructField {
 | 
						|
	return i.v.Type().FieldByIndex(i.index)
 | 
						|
}
 | 
						|
 | 
						|
type visitor func(v reflect.Value) error
 | 
						|
 | 
						|
var stopDescent = fmt.Errorf("do not recurse")
 | 
						|
 | 
						|
func (f visitor) visit(x interface{}) error {
 | 
						|
	return f.visitRec(reflect.ValueOf(x))
 | 
						|
}
 | 
						|
 | 
						|
// visit recursively calls f on all nodes in v.
 | 
						|
func (f visitor) visitRec(v reflect.Value) error {
 | 
						|
	if v.Kind() == reflect.Ptr {
 | 
						|
		if v.IsNil() {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		return f.visitRec(v.Elem())
 | 
						|
	}
 | 
						|
	if err := f(v); err != nil {
 | 
						|
		if err == stopDescent {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	switch v.Kind() {
 | 
						|
	case reflect.Struct:
 | 
						|
		for i := iter(v); !i.done(); i.next() {
 | 
						|
			if err := f.visitRec(i.value()); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
		}
 | 
						|
	case reflect.Slice:
 | 
						|
		for i := 0; i < v.Len(); i++ {
 | 
						|
			if err := f.visitRec(v.Index(i)); err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// getPath is used for error reporting purposes only.
 | 
						|
func getPath(e Elem) string {
 | 
						|
	if e == nil {
 | 
						|
		return "<nil>"
 | 
						|
	}
 | 
						|
	if e.enclosing() == nil {
 | 
						|
		return e.GetCommon().name
 | 
						|
	}
 | 
						|
	if e.GetCommon().Type == "" {
 | 
						|
		return fmt.Sprintf("%s.%s", getPath(e.enclosing()), e.GetCommon().name)
 | 
						|
	}
 | 
						|
	return fmt.Sprintf("%s.%s[type=%s]", getPath(e.enclosing()), e.GetCommon().name, e.GetCommon().Type)
 | 
						|
}
 | 
						|
 | 
						|
// xmlName returns the xml name of the element or attribute
 | 
						|
func xmlName(f reflect.StructField) (name string, attr bool) {
 | 
						|
	tags := strings.Split(f.Tag.Get("xml"), ",")
 | 
						|
	for _, s := range tags {
 | 
						|
		attr = attr || s == "attr"
 | 
						|
	}
 | 
						|
	return tags[0], attr
 | 
						|
}
 | 
						|
 | 
						|
func findField(v reflect.Value, key string) (reflect.Value, error) {
 | 
						|
	v = reflect.Indirect(v)
 | 
						|
	for i := iter(v); !i.done(); i.next() {
 | 
						|
		if n, _ := xmlName(i.field()); n == key {
 | 
						|
			return i.value(), nil
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return reflect.Value{}, fmt.Errorf("cldr: no field %q in element %#v", key, v.Interface())
 | 
						|
}
 | 
						|
 | 
						|
var xpathPart = regexp.MustCompile(`(\pL+)(?:\[@(\pL+)='([\w-]+)'\])?`)
 | 
						|
 | 
						|
func walkXPath(e Elem, path string) (res Elem, err error) {
 | 
						|
	for _, c := range strings.Split(path, "/") {
 | 
						|
		if c == ".." {
 | 
						|
			if e = e.enclosing(); e == nil {
 | 
						|
				panic("path ..")
 | 
						|
				return nil, fmt.Errorf(`cldr: ".." moves past root in path %q`, path)
 | 
						|
			}
 | 
						|
			continue
 | 
						|
		} else if c == "" {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		m := xpathPart.FindStringSubmatch(c)
 | 
						|
		if len(m) == 0 || len(m[0]) != len(c) {
 | 
						|
			return nil, fmt.Errorf("cldr: syntax error in path component %q", c)
 | 
						|
		}
 | 
						|
		v, err := findField(reflect.ValueOf(e), m[1])
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		switch v.Kind() {
 | 
						|
		case reflect.Slice:
 | 
						|
			i := 0
 | 
						|
			if m[2] != "" || v.Len() > 1 {
 | 
						|
				if m[2] == "" {
 | 
						|
					m[2] = "type"
 | 
						|
					if m[3] = e.GetCommon().Default(); m[3] == "" {
 | 
						|
						return nil, fmt.Errorf("cldr: type selector or default value needed for element %s", m[1])
 | 
						|
					}
 | 
						|
				}
 | 
						|
				for ; i < v.Len(); i++ {
 | 
						|
					vi := v.Index(i)
 | 
						|
					key, err := findField(vi.Elem(), m[2])
 | 
						|
					if err != nil {
 | 
						|
						return nil, err
 | 
						|
					}
 | 
						|
					key = reflect.Indirect(key)
 | 
						|
					if key.Kind() == reflect.String && key.String() == m[3] {
 | 
						|
						break
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			if i == v.Len() || v.Index(i).IsNil() {
 | 
						|
				return nil, fmt.Errorf("no %s found with %s==%s", m[1], m[2], m[3])
 | 
						|
			}
 | 
						|
			e = v.Index(i).Interface().(Elem)
 | 
						|
		case reflect.Ptr:
 | 
						|
			if v.IsNil() {
 | 
						|
				return nil, fmt.Errorf("cldr: element %q not found within element %q", m[1], e.GetCommon().name)
 | 
						|
			}
 | 
						|
			var ok bool
 | 
						|
			if e, ok = v.Interface().(Elem); !ok {
 | 
						|
				return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
 | 
						|
			} else if m[2] != "" || m[3] != "" {
 | 
						|
				return nil, fmt.Errorf("cldr: no type selector allowed for element %s", m[1])
 | 
						|
			}
 | 
						|
		default:
 | 
						|
			return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return e, nil
 | 
						|
}
 | 
						|
 | 
						|
const absPrefix = "//ldml/"
 | 
						|
 | 
						|
func (cldr *CLDR) resolveAlias(e Elem, src, path string) (res Elem, err error) {
 | 
						|
	if src != "locale" {
 | 
						|
		if !strings.HasPrefix(path, absPrefix) {
 | 
						|
			return nil, fmt.Errorf("cldr: expected absolute path, found %q", path)
 | 
						|
		}
 | 
						|
		path = path[len(absPrefix):]
 | 
						|
		if e, err = cldr.resolve(src); err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return walkXPath(e, path)
 | 
						|
}
 | 
						|
 | 
						|
func (cldr *CLDR) resolveAndMergeAlias(e Elem) error {
 | 
						|
	alias := e.GetCommon().Alias
 | 
						|
	if alias == nil {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	a, err := cldr.resolveAlias(e, alias.Source, alias.Path)
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("%v: error evaluating path %q: %v", getPath(e), alias.Path, err)
 | 
						|
	}
 | 
						|
	// Ensure alias node was already evaluated. TODO: avoid double evaluation.
 | 
						|
	err = cldr.resolveAndMergeAlias(a)
 | 
						|
	v := reflect.ValueOf(e).Elem()
 | 
						|
	for i := iter(reflect.ValueOf(a).Elem()); !i.done(); i.next() {
 | 
						|
		if vv := i.value(); vv.Kind() != reflect.Ptr || !vv.IsNil() {
 | 
						|
			if _, attr := xmlName(i.field()); !attr {
 | 
						|
				v.FieldByIndex(i.index).Set(vv)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return err
 | 
						|
}
 | 
						|
 | 
						|
func (cldr *CLDR) aliasResolver() visitor {
 | 
						|
	return func(v reflect.Value) (err error) {
 | 
						|
		if e, ok := v.Addr().Interface().(Elem); ok {
 | 
						|
			err = cldr.resolveAndMergeAlias(e)
 | 
						|
			if err == nil && blocking[e.GetCommon().name] {
 | 
						|
				return stopDescent
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return err
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// elements within blocking elements do not inherit.
 | 
						|
// Taken from CLDR's supplementalMetaData.xml.
 | 
						|
var blocking = map[string]bool{
 | 
						|
	"identity":         true,
 | 
						|
	"supplementalData": true,
 | 
						|
	"cldrTest":         true,
 | 
						|
	"collation":        true,
 | 
						|
	"transform":        true,
 | 
						|
}
 | 
						|
 | 
						|
// Distinguishing attributes affect inheritance; two elements with different
 | 
						|
// distinguishing attributes are treated as different for purposes of inheritance,
 | 
						|
// except when such attributes occur in the indicated elements.
 | 
						|
// Taken from CLDR's supplementalMetaData.xml.
 | 
						|
var distinguishing = map[string][]string{
 | 
						|
	"key":        nil,
 | 
						|
	"request_id": nil,
 | 
						|
	"id":         nil,
 | 
						|
	"registry":   nil,
 | 
						|
	"alt":        nil,
 | 
						|
	"iso4217":    nil,
 | 
						|
	"iso3166":    nil,
 | 
						|
	"mzone":      nil,
 | 
						|
	"from":       nil,
 | 
						|
	"to":         nil,
 | 
						|
	"type": []string{
 | 
						|
		"abbreviationFallback",
 | 
						|
		"default",
 | 
						|
		"mapping",
 | 
						|
		"measurementSystem",
 | 
						|
		"preferenceOrdering",
 | 
						|
	},
 | 
						|
	"numberSystem": nil,
 | 
						|
}
 | 
						|
 | 
						|
func in(set []string, s string) bool {
 | 
						|
	for _, v := range set {
 | 
						|
		if v == s {
 | 
						|
			return true
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
// attrKey computes a key based on the distinguishable attributes of
 | 
						|
// an element and it's values.
 | 
						|
func attrKey(v reflect.Value, exclude ...string) string {
 | 
						|
	parts := []string{}
 | 
						|
	ename := v.Interface().(Elem).GetCommon().name
 | 
						|
	v = v.Elem()
 | 
						|
	for i := iter(v); !i.done(); i.next() {
 | 
						|
		if name, attr := xmlName(i.field()); attr {
 | 
						|
			if except, ok := distinguishing[name]; ok && !in(exclude, name) && !in(except, ename) {
 | 
						|
				v := i.value()
 | 
						|
				if v.Kind() == reflect.Ptr {
 | 
						|
					v = v.Elem()
 | 
						|
				}
 | 
						|
				if v.IsValid() {
 | 
						|
					parts = append(parts, fmt.Sprintf("%s=%s", name, v.String()))
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	sort.Strings(parts)
 | 
						|
	return strings.Join(parts, ";")
 | 
						|
}
 | 
						|
 | 
						|
// Key returns a key for e derived from all distinguishing attributes
 | 
						|
// except those specified by exclude.
 | 
						|
func Key(e Elem, exclude ...string) string {
 | 
						|
	return attrKey(reflect.ValueOf(e), exclude...)
 | 
						|
}
 | 
						|
 | 
						|
// linkEnclosing sets the enclosing element as well as the name
 | 
						|
// for all sub-elements of child, recursively.
 | 
						|
func linkEnclosing(parent, child Elem) {
 | 
						|
	child.setEnclosing(parent)
 | 
						|
	v := reflect.ValueOf(child).Elem()
 | 
						|
	for i := iter(v); !i.done(); i.next() {
 | 
						|
		vf := i.value()
 | 
						|
		if vf.Kind() == reflect.Slice {
 | 
						|
			for j := 0; j < vf.Len(); j++ {
 | 
						|
				linkEnclosing(child, vf.Index(j).Interface().(Elem))
 | 
						|
			}
 | 
						|
		} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
 | 
						|
			linkEnclosing(child, vf.Interface().(Elem))
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func setNames(e Elem, name string) {
 | 
						|
	e.setName(name)
 | 
						|
	v := reflect.ValueOf(e).Elem()
 | 
						|
	for i := iter(v); !i.done(); i.next() {
 | 
						|
		vf := i.value()
 | 
						|
		name, _ = xmlName(i.field())
 | 
						|
		if vf.Kind() == reflect.Slice {
 | 
						|
			for j := 0; j < vf.Len(); j++ {
 | 
						|
				setNames(vf.Index(j).Interface().(Elem), name)
 | 
						|
			}
 | 
						|
		} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
 | 
						|
			setNames(vf.Interface().(Elem), name)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// deepCopy copies elements of v recursively.  All elements of v that may
 | 
						|
// be modified by inheritance are explicitly copied.
 | 
						|
func deepCopy(v reflect.Value) reflect.Value {
 | 
						|
	switch v.Kind() {
 | 
						|
	case reflect.Ptr:
 | 
						|
		if v.IsNil() || v.Elem().Kind() != reflect.Struct {
 | 
						|
			return v
 | 
						|
		}
 | 
						|
		nv := reflect.New(v.Elem().Type())
 | 
						|
		nv.Elem().Set(v.Elem())
 | 
						|
		deepCopyRec(nv.Elem(), v.Elem())
 | 
						|
		return nv
 | 
						|
	case reflect.Slice:
 | 
						|
		nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
 | 
						|
		for i := 0; i < v.Len(); i++ {
 | 
						|
			deepCopyRec(nv.Index(i), v.Index(i))
 | 
						|
		}
 | 
						|
		return nv
 | 
						|
	}
 | 
						|
	panic("deepCopy: must be called with pointer or slice")
 | 
						|
}
 | 
						|
 | 
						|
// deepCopyRec is only called by deepCopy.
 | 
						|
func deepCopyRec(nv, v reflect.Value) {
 | 
						|
	if v.Kind() == reflect.Struct {
 | 
						|
		t := v.Type()
 | 
						|
		for i := 0; i < v.NumField(); i++ {
 | 
						|
			if name, attr := xmlName(t.Field(i)); name != "" && !attr {
 | 
						|
				deepCopyRec(nv.Field(i), v.Field(i))
 | 
						|
			}
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		nv.Set(deepCopy(v))
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// newNode is used to insert a missing node during inheritance.
 | 
						|
func (cldr *CLDR) newNode(v, enc reflect.Value) reflect.Value {
 | 
						|
	n := reflect.New(v.Type())
 | 
						|
	for i := iter(v); !i.done(); i.next() {
 | 
						|
		if name, attr := xmlName(i.field()); name == "" || attr {
 | 
						|
			n.Elem().FieldByIndex(i.index).Set(i.value())
 | 
						|
		}
 | 
						|
	}
 | 
						|
	n.Interface().(Elem).GetCommon().setEnclosing(enc.Addr().Interface().(Elem))
 | 
						|
	return n
 | 
						|
}
 | 
						|
 | 
						|
// v, parent must be pointers to struct
 | 
						|
func (cldr *CLDR) inheritFields(v, parent reflect.Value) (res reflect.Value, err error) {
 | 
						|
	t := v.Type()
 | 
						|
	nv := reflect.New(t)
 | 
						|
	nv.Elem().Set(v)
 | 
						|
	for i := iter(v); !i.done(); i.next() {
 | 
						|
		vf := i.value()
 | 
						|
		f := i.field()
 | 
						|
		name, attr := xmlName(f)
 | 
						|
		if name == "" || attr {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		pf := parent.FieldByIndex(i.index)
 | 
						|
		if blocking[name] {
 | 
						|
			if vf.IsNil() {
 | 
						|
				vf = pf
 | 
						|
			}
 | 
						|
			nv.Elem().FieldByIndex(i.index).Set(deepCopy(vf))
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		switch f.Type.Kind() {
 | 
						|
		case reflect.Ptr:
 | 
						|
			if f.Type.Elem().Kind() == reflect.Struct {
 | 
						|
				if !vf.IsNil() {
 | 
						|
					if vf, err = cldr.inheritStructPtr(vf, pf); err != nil {
 | 
						|
						return reflect.Value{}, err
 | 
						|
					}
 | 
						|
					vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
 | 
						|
					nv.Elem().FieldByIndex(i.index).Set(vf)
 | 
						|
				} else if !pf.IsNil() {
 | 
						|
					n := cldr.newNode(pf.Elem(), v)
 | 
						|
					if vf, err = cldr.inheritStructPtr(n, pf); err != nil {
 | 
						|
						return reflect.Value{}, err
 | 
						|
					}
 | 
						|
					vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
 | 
						|
					nv.Elem().FieldByIndex(i.index).Set(vf)
 | 
						|
				}
 | 
						|
			}
 | 
						|
		case reflect.Slice:
 | 
						|
			vf, err := cldr.inheritSlice(nv.Elem(), vf, pf)
 | 
						|
			if err != nil {
 | 
						|
				return reflect.Zero(t), err
 | 
						|
			}
 | 
						|
			nv.Elem().FieldByIndex(i.index).Set(vf)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nv, nil
 | 
						|
}
 | 
						|
 | 
						|
func root(e Elem) *LDML {
 | 
						|
	for ; e.enclosing() != nil; e = e.enclosing() {
 | 
						|
	}
 | 
						|
	return e.(*LDML)
 | 
						|
}
 | 
						|
 | 
						|
// inheritStructPtr first merges possible aliases in with v and then inherits
 | 
						|
// any underspecified elements from parent.
 | 
						|
func (cldr *CLDR) inheritStructPtr(v, parent reflect.Value) (r reflect.Value, err error) {
 | 
						|
	if !v.IsNil() {
 | 
						|
		e := v.Interface().(Elem).GetCommon()
 | 
						|
		alias := e.Alias
 | 
						|
		if alias == nil && !parent.IsNil() {
 | 
						|
			alias = parent.Interface().(Elem).GetCommon().Alias
 | 
						|
		}
 | 
						|
		if alias != nil {
 | 
						|
			a, err := cldr.resolveAlias(v.Interface().(Elem), alias.Source, alias.Path)
 | 
						|
			if a != nil {
 | 
						|
				if v, err = cldr.inheritFields(v.Elem(), reflect.ValueOf(a).Elem()); err != nil {
 | 
						|
					return reflect.Value{}, err
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if !parent.IsNil() {
 | 
						|
			return cldr.inheritFields(v.Elem(), parent.Elem())
 | 
						|
		}
 | 
						|
	} else if parent.IsNil() {
 | 
						|
		panic("should not reach here")
 | 
						|
	}
 | 
						|
	return v, nil
 | 
						|
}
 | 
						|
 | 
						|
// Must be slice of struct pointers.
 | 
						|
func (cldr *CLDR) inheritSlice(enc, v, parent reflect.Value) (res reflect.Value, err error) {
 | 
						|
	t := v.Type()
 | 
						|
	index := make(map[string]reflect.Value)
 | 
						|
	if !v.IsNil() {
 | 
						|
		for i := 0; i < v.Len(); i++ {
 | 
						|
			vi := v.Index(i)
 | 
						|
			key := attrKey(vi)
 | 
						|
			index[key] = vi
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if !parent.IsNil() {
 | 
						|
		for i := 0; i < parent.Len(); i++ {
 | 
						|
			vi := parent.Index(i)
 | 
						|
			key := attrKey(vi)
 | 
						|
			if w, ok := index[key]; ok {
 | 
						|
				index[key], err = cldr.inheritStructPtr(w, vi)
 | 
						|
			} else {
 | 
						|
				n := cldr.newNode(vi.Elem(), enc)
 | 
						|
				index[key], err = cldr.inheritStructPtr(n, vi)
 | 
						|
			}
 | 
						|
			index[key].Interface().(Elem).setEnclosing(enc.Addr().Interface().(Elem))
 | 
						|
			if err != nil {
 | 
						|
				return v, err
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	keys := make([]string, 0, len(index))
 | 
						|
	for k, _ := range index {
 | 
						|
		keys = append(keys, k)
 | 
						|
	}
 | 
						|
	sort.Strings(keys)
 | 
						|
	sl := reflect.MakeSlice(t, len(index), len(index))
 | 
						|
	for i, k := range keys {
 | 
						|
		sl.Index(i).Set(index[k])
 | 
						|
	}
 | 
						|
	return sl, nil
 | 
						|
}
 | 
						|
 | 
						|
func parentLocale(loc string) string {
 | 
						|
	parts := strings.Split(loc, "_")
 | 
						|
	if len(parts) == 1 {
 | 
						|
		return "root"
 | 
						|
	}
 | 
						|
	parts = parts[:len(parts)-1]
 | 
						|
	key := strings.Join(parts, "_")
 | 
						|
	return key
 | 
						|
}
 | 
						|
 | 
						|
func (cldr *CLDR) resolve(loc string) (res *LDML, err error) {
 | 
						|
	if r := cldr.resolved[loc]; r != nil {
 | 
						|
		return r, nil
 | 
						|
	}
 | 
						|
	x := cldr.RawLDML(loc)
 | 
						|
	if x == nil {
 | 
						|
		return nil, fmt.Errorf("cldr: unknown locale %q", loc)
 | 
						|
	}
 | 
						|
	var v reflect.Value
 | 
						|
	if loc == "root" {
 | 
						|
		x = deepCopy(reflect.ValueOf(x)).Interface().(*LDML)
 | 
						|
		linkEnclosing(nil, x)
 | 
						|
		err = cldr.aliasResolver().visit(x)
 | 
						|
	} else {
 | 
						|
		key := parentLocale(loc)
 | 
						|
		var parent *LDML
 | 
						|
		for ; cldr.locale[key] == nil; key = parentLocale(key) {
 | 
						|
		}
 | 
						|
		if parent, err = cldr.resolve(key); err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		v, err = cldr.inheritFields(reflect.ValueOf(x).Elem(), reflect.ValueOf(parent).Elem())
 | 
						|
		x = v.Interface().(*LDML)
 | 
						|
		linkEnclosing(nil, x)
 | 
						|
	}
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	cldr.resolved[loc] = x
 | 
						|
	return x, err
 | 
						|
}
 | 
						|
 | 
						|
// finalize finalizes the initialization of the raw LDML structs.  It also
 | 
						|
// removed unwanted fields, as specified by filter, so that they will not
 | 
						|
// be unnecessarily evaluated.
 | 
						|
func (cldr *CLDR) finalize(filter []string) {
 | 
						|
	for _, x := range cldr.locale {
 | 
						|
		if filter != nil {
 | 
						|
			v := reflect.ValueOf(x).Elem()
 | 
						|
			t := v.Type()
 | 
						|
			for i := 0; i < v.NumField(); i++ {
 | 
						|
				f := t.Field(i)
 | 
						|
				name, _ := xmlName(f)
 | 
						|
				if name != "" && name != "identity" && !in(filter, name) {
 | 
						|
					v.Field(i).Set(reflect.Zero(f.Type))
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		linkEnclosing(nil, x) // for resolving aliases and paths
 | 
						|
		setNames(x, "ldml")
 | 
						|
	}
 | 
						|
}
 |