gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/golang.org/x/text/unicode/cldr/resolve.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cldr
     6  
     7  // This file implements the various inheritance constructs defined by LDML.
     8  // See http://www.unicode.org/reports/tr35/#Inheritance_and_Validity
     9  // for more details.
    10  
    11  import (
    12  	"fmt"
    13  	"log"
    14  	"reflect"
    15  	"regexp"
    16  	"sort"
    17  	"strings"
    18  )
    19  
    20  // fieldIter iterates over fields in a struct. It includes
    21  // fields of embedded structs.
    22  type fieldIter struct {
    23  	v        reflect.Value
    24  	index, n []int
    25  }
    26  
    27  func iter(v reflect.Value) fieldIter {
    28  	if v.Kind() != reflect.Struct {
    29  		log.Panicf("value %v must be a struct", v)
    30  	}
    31  	i := fieldIter{
    32  		v:     v,
    33  		index: []int{0},
    34  		n:     []int{v.NumField()},
    35  	}
    36  	i.descent()
    37  	return i
    38  }
    39  
    40  func (i *fieldIter) descent() {
    41  	for f := i.field(); f.Anonymous && f.Type.NumField() > 0; f = i.field() {
    42  		i.index = append(i.index, 0)
    43  		i.n = append(i.n, f.Type.NumField())
    44  	}
    45  }
    46  
    47  func (i *fieldIter) done() bool {
    48  	return len(i.index) == 1 && i.index[0] >= i.n[0]
    49  }
    50  
    51  func skip(f reflect.StructField) bool {
    52  	return !f.Anonymous && (f.Name[0] < 'A' || f.Name[0] > 'Z')
    53  }
    54  
    55  func (i *fieldIter) next() {
    56  	for {
    57  		k := len(i.index) - 1
    58  		i.index[k]++
    59  		if i.index[k] < i.n[k] {
    60  			if !skip(i.field()) {
    61  				break
    62  			}
    63  		} else {
    64  			if k == 0 {
    65  				return
    66  			}
    67  			i.index = i.index[:k]
    68  			i.n = i.n[:k]
    69  		}
    70  	}
    71  	i.descent()
    72  }
    73  
    74  func (i *fieldIter) value() reflect.Value {
    75  	return i.v.FieldByIndex(i.index)
    76  }
    77  
    78  func (i *fieldIter) field() reflect.StructField {
    79  	return i.v.Type().FieldByIndex(i.index)
    80  }
    81  
    82  type visitor func(v reflect.Value) error
    83  
    84  var stopDescent = fmt.Errorf("do not recurse")
    85  
    86  func (f visitor) visit(x interface{}) error {
    87  	return f.visitRec(reflect.ValueOf(x))
    88  }
    89  
    90  // visit recursively calls f on all nodes in v.
    91  func (f visitor) visitRec(v reflect.Value) error {
    92  	if v.Kind() == reflect.Ptr {
    93  		if v.IsNil() {
    94  			return nil
    95  		}
    96  		return f.visitRec(v.Elem())
    97  	}
    98  	if err := f(v); err != nil {
    99  		if err == stopDescent {
   100  			return nil
   101  		}
   102  		return err
   103  	}
   104  	switch v.Kind() {
   105  	case reflect.Struct:
   106  		for i := iter(v); !i.done(); i.next() {
   107  			if err := f.visitRec(i.value()); err != nil {
   108  				return err
   109  			}
   110  		}
   111  	case reflect.Slice:
   112  		for i := 0; i < v.Len(); i++ {
   113  			if err := f.visitRec(v.Index(i)); err != nil {
   114  				return err
   115  			}
   116  		}
   117  	}
   118  	return nil
   119  }
   120  
   121  // getPath is used for error reporting purposes only.
   122  func getPath(e Elem) string {
   123  	if e == nil {
   124  		return "<nil>"
   125  	}
   126  	if e.enclosing() == nil {
   127  		return e.GetCommon().name
   128  	}
   129  	if e.GetCommon().Type == "" {
   130  		return fmt.Sprintf("%s.%s", getPath(e.enclosing()), e.GetCommon().name)
   131  	}
   132  	return fmt.Sprintf("%s.%s[type=%s]", getPath(e.enclosing()), e.GetCommon().name, e.GetCommon().Type)
   133  }
   134  
   135  // xmlName returns the xml name of the element or attribute
   136  func xmlName(f reflect.StructField) (name string, attr bool) {
   137  	tags := strings.Split(f.Tag.Get("xml"), ",")
   138  	for _, s := range tags {
   139  		attr = attr || s == "attr"
   140  	}
   141  	return tags[0], attr
   142  }
   143  
   144  func findField(v reflect.Value, key string) (reflect.Value, error) {
   145  	v = reflect.Indirect(v)
   146  	for i := iter(v); !i.done(); i.next() {
   147  		if n, _ := xmlName(i.field()); n == key {
   148  			return i.value(), nil
   149  		}
   150  	}
   151  	return reflect.Value{}, fmt.Errorf("cldr: no field %q in element %#v", key, v.Interface())
   152  }
   153  
   154  var xpathPart = regexp.MustCompile(`(\pL+)(?:\[@(\pL+)='([\w-]+)'\])?`)
   155  
   156  func walkXPath(e Elem, path string) (res Elem, err error) {
   157  	for _, c := range strings.Split(path, "/") {
   158  		if c == ".." {
   159  			if e = e.enclosing(); e == nil {
   160  				panic("path ..")
   161  				return nil, fmt.Errorf(`cldr: ".." moves past root in path %q`, path)
   162  			}
   163  			continue
   164  		} else if c == "" {
   165  			continue
   166  		}
   167  		m := xpathPart.FindStringSubmatch(c)
   168  		if len(m) == 0 || len(m[0]) != len(c) {
   169  			return nil, fmt.Errorf("cldr: syntax error in path component %q", c)
   170  		}
   171  		v, err := findField(reflect.ValueOf(e), m[1])
   172  		if err != nil {
   173  			return nil, err
   174  		}
   175  		switch v.Kind() {
   176  		case reflect.Slice:
   177  			i := 0
   178  			if m[2] != "" || v.Len() > 1 {
   179  				if m[2] == "" {
   180  					m[2] = "type"
   181  					if m[3] = e.GetCommon().Default(); m[3] == "" {
   182  						return nil, fmt.Errorf("cldr: type selector or default value needed for element %s", m[1])
   183  					}
   184  				}
   185  				for ; i < v.Len(); i++ {
   186  					vi := v.Index(i)
   187  					key, err := findField(vi.Elem(), m[2])
   188  					if err != nil {
   189  						return nil, err
   190  					}
   191  					key = reflect.Indirect(key)
   192  					if key.Kind() == reflect.String && key.String() == m[3] {
   193  						break
   194  					}
   195  				}
   196  			}
   197  			if i == v.Len() || v.Index(i).IsNil() {
   198  				return nil, fmt.Errorf("no %s found with %s==%s", m[1], m[2], m[3])
   199  			}
   200  			e = v.Index(i).Interface().(Elem)
   201  		case reflect.Ptr:
   202  			if v.IsNil() {
   203  				return nil, fmt.Errorf("cldr: element %q not found within element %q", m[1], e.GetCommon().name)
   204  			}
   205  			var ok bool
   206  			if e, ok = v.Interface().(Elem); !ok {
   207  				return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
   208  			} else if m[2] != "" || m[3] != "" {
   209  				return nil, fmt.Errorf("cldr: no type selector allowed for element %s", m[1])
   210  			}
   211  		default:
   212  			return nil, fmt.Errorf("cldr: %q is not an XML element", m[1])
   213  		}
   214  	}
   215  	return e, nil
   216  }
   217  
   218  const absPrefix = "//ldml/"
   219  
   220  func (cldr *CLDR) resolveAlias(e Elem, src, path string) (res Elem, err error) {
   221  	if src != "locale" {
   222  		if !strings.HasPrefix(path, absPrefix) {
   223  			return nil, fmt.Errorf("cldr: expected absolute path, found %q", path)
   224  		}
   225  		path = path[len(absPrefix):]
   226  		if e, err = cldr.resolve(src); err != nil {
   227  			return nil, err
   228  		}
   229  	}
   230  	return walkXPath(e, path)
   231  }
   232  
   233  func (cldr *CLDR) resolveAndMergeAlias(e Elem) error {
   234  	alias := e.GetCommon().Alias
   235  	if alias == nil {
   236  		return nil
   237  	}
   238  	a, err := cldr.resolveAlias(e, alias.Source, alias.Path)
   239  	if err != nil {
   240  		return fmt.Errorf("%v: error evaluating path %q: %v", getPath(e), alias.Path, err)
   241  	}
   242  	// Ensure alias node was already evaluated. TODO: avoid double evaluation.
   243  	err = cldr.resolveAndMergeAlias(a)
   244  	v := reflect.ValueOf(e).Elem()
   245  	for i := iter(reflect.ValueOf(a).Elem()); !i.done(); i.next() {
   246  		if vv := i.value(); vv.Kind() != reflect.Ptr || !vv.IsNil() {
   247  			if _, attr := xmlName(i.field()); !attr {
   248  				v.FieldByIndex(i.index).Set(vv)
   249  			}
   250  		}
   251  	}
   252  	return err
   253  }
   254  
   255  func (cldr *CLDR) aliasResolver() visitor {
   256  	return func(v reflect.Value) (err error) {
   257  		if e, ok := v.Addr().Interface().(Elem); ok {
   258  			err = cldr.resolveAndMergeAlias(e)
   259  			if err == nil && blocking[e.GetCommon().name] {
   260  				return stopDescent
   261  			}
   262  		}
   263  		return err
   264  	}
   265  }
   266  
   267  // elements within blocking elements do not inherit.
   268  // Taken from CLDR's supplementalMetaData.xml.
   269  var blocking = map[string]bool{
   270  	"identity":         true,
   271  	"supplementalData": true,
   272  	"cldrTest":         true,
   273  	"collation":        true,
   274  	"transform":        true,
   275  }
   276  
   277  // Distinguishing attributes affect inheritance; two elements with different
   278  // distinguishing attributes are treated as different for purposes of inheritance,
   279  // except when such attributes occur in the indicated elements.
   280  // Taken from CLDR's supplementalMetaData.xml.
   281  var distinguishing = map[string][]string{
   282  	"key":        nil,
   283  	"request_id": nil,
   284  	"id":         nil,
   285  	"registry":   nil,
   286  	"alt":        nil,
   287  	"iso4217":    nil,
   288  	"iso3166":    nil,
   289  	"mzone":      nil,
   290  	"from":       nil,
   291  	"to":         nil,
   292  	"type": []string{
   293  		"abbreviationFallback",
   294  		"default",
   295  		"mapping",
   296  		"measurementSystem",
   297  		"preferenceOrdering",
   298  	},
   299  	"numberSystem": nil,
   300  }
   301  
   302  func in(set []string, s string) bool {
   303  	for _, v := range set {
   304  		if v == s {
   305  			return true
   306  		}
   307  	}
   308  	return false
   309  }
   310  
   311  // attrKey computes a key based on the distinguishable attributes of
   312  // an element and it's values.
   313  func attrKey(v reflect.Value, exclude ...string) string {
   314  	parts := []string{}
   315  	ename := v.Interface().(Elem).GetCommon().name
   316  	v = v.Elem()
   317  	for i := iter(v); !i.done(); i.next() {
   318  		if name, attr := xmlName(i.field()); attr {
   319  			if except, ok := distinguishing[name]; ok && !in(exclude, name) && !in(except, ename) {
   320  				v := i.value()
   321  				if v.Kind() == reflect.Ptr {
   322  					v = v.Elem()
   323  				}
   324  				if v.IsValid() {
   325  					parts = append(parts, fmt.Sprintf("%s=%s", name, v.String()))
   326  				}
   327  			}
   328  		}
   329  	}
   330  	sort.Strings(parts)
   331  	return strings.Join(parts, ";")
   332  }
   333  
   334  // Key returns a key for e derived from all distinguishing attributes
   335  // except those specified by exclude.
   336  func Key(e Elem, exclude ...string) string {
   337  	return attrKey(reflect.ValueOf(e), exclude...)
   338  }
   339  
   340  // linkEnclosing sets the enclosing element as well as the name
   341  // for all sub-elements of child, recursively.
   342  func linkEnclosing(parent, child Elem) {
   343  	child.setEnclosing(parent)
   344  	v := reflect.ValueOf(child).Elem()
   345  	for i := iter(v); !i.done(); i.next() {
   346  		vf := i.value()
   347  		if vf.Kind() == reflect.Slice {
   348  			for j := 0; j < vf.Len(); j++ {
   349  				linkEnclosing(child, vf.Index(j).Interface().(Elem))
   350  			}
   351  		} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
   352  			linkEnclosing(child, vf.Interface().(Elem))
   353  		}
   354  	}
   355  }
   356  
   357  func setNames(e Elem, name string) {
   358  	e.setName(name)
   359  	v := reflect.ValueOf(e).Elem()
   360  	for i := iter(v); !i.done(); i.next() {
   361  		vf := i.value()
   362  		name, _ = xmlName(i.field())
   363  		if vf.Kind() == reflect.Slice {
   364  			for j := 0; j < vf.Len(); j++ {
   365  				setNames(vf.Index(j).Interface().(Elem), name)
   366  			}
   367  		} else if vf.Kind() == reflect.Ptr && !vf.IsNil() && vf.Elem().Kind() == reflect.Struct {
   368  			setNames(vf.Interface().(Elem), name)
   369  		}
   370  	}
   371  }
   372  
   373  // deepCopy copies elements of v recursively.  All elements of v that may
   374  // be modified by inheritance are explicitly copied.
   375  func deepCopy(v reflect.Value) reflect.Value {
   376  	switch v.Kind() {
   377  	case reflect.Ptr:
   378  		if v.IsNil() || v.Elem().Kind() != reflect.Struct {
   379  			return v
   380  		}
   381  		nv := reflect.New(v.Elem().Type())
   382  		nv.Elem().Set(v.Elem())
   383  		deepCopyRec(nv.Elem(), v.Elem())
   384  		return nv
   385  	case reflect.Slice:
   386  		nv := reflect.MakeSlice(v.Type(), v.Len(), v.Len())
   387  		for i := 0; i < v.Len(); i++ {
   388  			deepCopyRec(nv.Index(i), v.Index(i))
   389  		}
   390  		return nv
   391  	}
   392  	panic("deepCopy: must be called with pointer or slice")
   393  }
   394  
   395  // deepCopyRec is only called by deepCopy.
   396  func deepCopyRec(nv, v reflect.Value) {
   397  	if v.Kind() == reflect.Struct {
   398  		t := v.Type()
   399  		for i := 0; i < v.NumField(); i++ {
   400  			if name, attr := xmlName(t.Field(i)); name != "" && !attr {
   401  				deepCopyRec(nv.Field(i), v.Field(i))
   402  			}
   403  		}
   404  	} else {
   405  		nv.Set(deepCopy(v))
   406  	}
   407  }
   408  
   409  // newNode is used to insert a missing node during inheritance.
   410  func (cldr *CLDR) newNode(v, enc reflect.Value) reflect.Value {
   411  	n := reflect.New(v.Type())
   412  	for i := iter(v); !i.done(); i.next() {
   413  		if name, attr := xmlName(i.field()); name == "" || attr {
   414  			n.Elem().FieldByIndex(i.index).Set(i.value())
   415  		}
   416  	}
   417  	n.Interface().(Elem).GetCommon().setEnclosing(enc.Addr().Interface().(Elem))
   418  	return n
   419  }
   420  
   421  // v, parent must be pointers to struct
   422  func (cldr *CLDR) inheritFields(v, parent reflect.Value) (res reflect.Value, err error) {
   423  	t := v.Type()
   424  	nv := reflect.New(t)
   425  	nv.Elem().Set(v)
   426  	for i := iter(v); !i.done(); i.next() {
   427  		vf := i.value()
   428  		f := i.field()
   429  		name, attr := xmlName(f)
   430  		if name == "" || attr {
   431  			continue
   432  		}
   433  		pf := parent.FieldByIndex(i.index)
   434  		if blocking[name] {
   435  			if vf.IsNil() {
   436  				vf = pf
   437  			}
   438  			nv.Elem().FieldByIndex(i.index).Set(deepCopy(vf))
   439  			continue
   440  		}
   441  		switch f.Type.Kind() {
   442  		case reflect.Ptr:
   443  			if f.Type.Elem().Kind() == reflect.Struct {
   444  				if !vf.IsNil() {
   445  					if vf, err = cldr.inheritStructPtr(vf, pf); err != nil {
   446  						return reflect.Value{}, err
   447  					}
   448  					vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
   449  					nv.Elem().FieldByIndex(i.index).Set(vf)
   450  				} else if !pf.IsNil() {
   451  					n := cldr.newNode(pf.Elem(), v)
   452  					if vf, err = cldr.inheritStructPtr(n, pf); err != nil {
   453  						return reflect.Value{}, err
   454  					}
   455  					vf.Interface().(Elem).setEnclosing(nv.Interface().(Elem))
   456  					nv.Elem().FieldByIndex(i.index).Set(vf)
   457  				}
   458  			}
   459  		case reflect.Slice:
   460  			vf, err := cldr.inheritSlice(nv.Elem(), vf, pf)
   461  			if err != nil {
   462  				return reflect.Zero(t), err
   463  			}
   464  			nv.Elem().FieldByIndex(i.index).Set(vf)
   465  		}
   466  	}
   467  	return nv, nil
   468  }
   469  
   470  func root(e Elem) *LDML {
   471  	for ; e.enclosing() != nil; e = e.enclosing() {
   472  	}
   473  	return e.(*LDML)
   474  }
   475  
   476  // inheritStructPtr first merges possible aliases in with v and then inherits
   477  // any underspecified elements from parent.
   478  func (cldr *CLDR) inheritStructPtr(v, parent reflect.Value) (r reflect.Value, err error) {
   479  	if !v.IsNil() {
   480  		e := v.Interface().(Elem).GetCommon()
   481  		alias := e.Alias
   482  		if alias == nil && !parent.IsNil() {
   483  			alias = parent.Interface().(Elem).GetCommon().Alias
   484  		}
   485  		if alias != nil {
   486  			a, err := cldr.resolveAlias(v.Interface().(Elem), alias.Source, alias.Path)
   487  			if a != nil {
   488  				if v, err = cldr.inheritFields(v.Elem(), reflect.ValueOf(a).Elem()); err != nil {
   489  					return reflect.Value{}, err
   490  				}
   491  			}
   492  		}
   493  		if !parent.IsNil() {
   494  			return cldr.inheritFields(v.Elem(), parent.Elem())
   495  		}
   496  	} else if parent.IsNil() {
   497  		panic("should not reach here")
   498  	}
   499  	return v, nil
   500  }
   501  
   502  // Must be slice of struct pointers.
   503  func (cldr *CLDR) inheritSlice(enc, v, parent reflect.Value) (res reflect.Value, err error) {
   504  	t := v.Type()
   505  	index := make(map[string]reflect.Value)
   506  	if !v.IsNil() {
   507  		for i := 0; i < v.Len(); i++ {
   508  			vi := v.Index(i)
   509  			key := attrKey(vi)
   510  			index[key] = vi
   511  		}
   512  	}
   513  	if !parent.IsNil() {
   514  		for i := 0; i < parent.Len(); i++ {
   515  			vi := parent.Index(i)
   516  			key := attrKey(vi)
   517  			if w, ok := index[key]; ok {
   518  				index[key], err = cldr.inheritStructPtr(w, vi)
   519  			} else {
   520  				n := cldr.newNode(vi.Elem(), enc)
   521  				index[key], err = cldr.inheritStructPtr(n, vi)
   522  			}
   523  			index[key].Interface().(Elem).setEnclosing(enc.Addr().Interface().(Elem))
   524  			if err != nil {
   525  				return v, err
   526  			}
   527  		}
   528  	}
   529  	keys := make([]string, 0, len(index))
   530  	for k, _ := range index {
   531  		keys = append(keys, k)
   532  	}
   533  	sort.Strings(keys)
   534  	sl := reflect.MakeSlice(t, len(index), len(index))
   535  	for i, k := range keys {
   536  		sl.Index(i).Set(index[k])
   537  	}
   538  	return sl, nil
   539  }
   540  
   541  func parentLocale(loc string) string {
   542  	parts := strings.Split(loc, "_")
   543  	if len(parts) == 1 {
   544  		return "root"
   545  	}
   546  	parts = parts[:len(parts)-1]
   547  	key := strings.Join(parts, "_")
   548  	return key
   549  }
   550  
   551  func (cldr *CLDR) resolve(loc string) (res *LDML, err error) {
   552  	if r := cldr.resolved[loc]; r != nil {
   553  		return r, nil
   554  	}
   555  	x := cldr.RawLDML(loc)
   556  	if x == nil {
   557  		return nil, fmt.Errorf("cldr: unknown locale %q", loc)
   558  	}
   559  	var v reflect.Value
   560  	if loc == "root" {
   561  		x = deepCopy(reflect.ValueOf(x)).Interface().(*LDML)
   562  		linkEnclosing(nil, x)
   563  		err = cldr.aliasResolver().visit(x)
   564  	} else {
   565  		key := parentLocale(loc)
   566  		var parent *LDML
   567  		for ; cldr.locale[key] == nil; key = parentLocale(key) {
   568  		}
   569  		if parent, err = cldr.resolve(key); err != nil {
   570  			return nil, err
   571  		}
   572  		v, err = cldr.inheritFields(reflect.ValueOf(x).Elem(), reflect.ValueOf(parent).Elem())
   573  		x = v.Interface().(*LDML)
   574  		linkEnclosing(nil, x)
   575  	}
   576  	if err != nil {
   577  		return nil, err
   578  	}
   579  	cldr.resolved[loc] = x
   580  	return x, err
   581  }
   582  
   583  // finalize finalizes the initialization of the raw LDML structs.  It also
   584  // removed unwanted fields, as specified by filter, so that they will not
   585  // be unnecessarily evaluated.
   586  func (cldr *CLDR) finalize(filter []string) {
   587  	for _, x := range cldr.locale {
   588  		if filter != nil {
   589  			v := reflect.ValueOf(x).Elem()
   590  			t := v.Type()
   591  			for i := 0; i < v.NumField(); i++ {
   592  				f := t.Field(i)
   593  				name, _ := xmlName(f)
   594  				if name != "" && name != "identity" && !in(filter, name) {
   595  					v.Field(i).Set(reflect.Zero(f.Type))
   596  				}
   597  			}
   598  		}
   599  		linkEnclosing(nil, x) // for resolving aliases and paths
   600  		setNames(x, "ldml")
   601  	}
   602  }