Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
105
vendor/golang.org/x/text/unicode/cldr/base.go
generated
vendored
Normal file
105
vendor/golang.org/x/text/unicode/cldr/base.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Elem is implemented by every XML element.
|
||||
type Elem interface {
|
||||
setEnclosing(Elem)
|
||||
setName(string)
|
||||
enclosing() Elem
|
||||
|
||||
GetCommon() *Common
|
||||
}
|
||||
|
||||
type hidden struct {
|
||||
CharData string `xml:",chardata"`
|
||||
Alias *struct {
|
||||
Common
|
||||
Source string `xml:"source,attr"`
|
||||
Path string `xml:"path,attr"`
|
||||
} `xml:"alias"`
|
||||
Def *struct {
|
||||
Common
|
||||
Choice string `xml:"choice,attr,omitempty"`
|
||||
Type string `xml:"type,attr,omitempty"`
|
||||
} `xml:"default"`
|
||||
}
|
||||
|
||||
// Common holds several of the most common attributes and sub elements
|
||||
// of an XML element.
|
||||
type Common struct {
|
||||
XMLName xml.Name
|
||||
name string
|
||||
enclElem Elem
|
||||
Type string `xml:"type,attr,omitempty"`
|
||||
Reference string `xml:"reference,attr,omitempty"`
|
||||
Alt string `xml:"alt,attr,omitempty"`
|
||||
ValidSubLocales string `xml:"validSubLocales,attr,omitempty"`
|
||||
Draft string `xml:"draft,attr,omitempty"`
|
||||
hidden
|
||||
}
|
||||
|
||||
// Default returns the default type to select from the enclosed list
|
||||
// or "" if no default value is specified.
|
||||
func (e *Common) Default() string {
|
||||
if e.Def == nil {
|
||||
return ""
|
||||
}
|
||||
if e.Def.Choice != "" {
|
||||
return e.Def.Choice
|
||||
} else if e.Def.Type != "" {
|
||||
// Type is still used by the default element in collation.
|
||||
return e.Def.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Element returns the XML element name.
|
||||
func (e *Common) Element() string {
|
||||
return e.name
|
||||
}
|
||||
|
||||
// GetCommon returns e. It is provided such that Common implements Elem.
|
||||
func (e *Common) GetCommon() *Common {
|
||||
return e
|
||||
}
|
||||
|
||||
// Data returns the character data accumulated for this element.
|
||||
func (e *Common) Data() string {
|
||||
e.CharData = charRe.ReplaceAllStringFunc(e.CharData, replaceUnicode)
|
||||
return e.CharData
|
||||
}
|
||||
|
||||
func (e *Common) setName(s string) {
|
||||
e.name = s
|
||||
}
|
||||
|
||||
func (e *Common) enclosing() Elem {
|
||||
return e.enclElem
|
||||
}
|
||||
|
||||
func (e *Common) setEnclosing(en Elem) {
|
||||
e.enclElem = en
|
||||
}
|
||||
|
||||
// Escape characters that can be escaped without further escaping the string.
|
||||
var charRe = regexp.MustCompile(`&#x[0-9a-fA-F]*;|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|\\x[0-9a-fA-F]{2}|\\[0-7]{3}|\\[abtnvfr]`)
|
||||
|
||||
// replaceUnicode converts hexadecimal Unicode codepoint notations to a one-rune string.
|
||||
// It assumes the input string is correctly formatted.
|
||||
func replaceUnicode(s string) string {
|
||||
if s[1] == '#' {
|
||||
r, _ := strconv.ParseInt(s[3:len(s)-1], 16, 32)
|
||||
return string(r)
|
||||
}
|
||||
r, _, _, _ := strconv.UnquoteChar(s, 0)
|
||||
return string(r)
|
||||
}
|
130
vendor/golang.org/x/text/unicode/cldr/cldr.go
generated
vendored
Normal file
130
vendor/golang.org/x/text/unicode/cldr/cldr.go
generated
vendored
Normal file
|
@ -0,0 +1,130 @@
|
|||
// 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.
|
||||
|
||||
//go:generate go run makexml.go -output xml.go
|
||||
|
||||
// Package cldr provides a parser for LDML and related XML formats.
|
||||
// This package is intended to be used by the table generation tools
|
||||
// for the various internationalization-related packages.
|
||||
// As the XML types are generated from the CLDR DTD, and as the CLDR standard
|
||||
// is periodically amended, this package may change considerably over time.
|
||||
// This mostly means that data may appear and disappear between versions.
|
||||
// That is, old code should keep compiling for newer versions, but data
|
||||
// may have moved or changed.
|
||||
// CLDR version 22 is the first version supported by this package.
|
||||
// Older versions may not work.
|
||||
package cldr // import "golang.org/x/text/unicode/cldr"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// CLDR provides access to parsed data of the Unicode Common Locale Data Repository.
|
||||
type CLDR struct {
|
||||
parent map[string][]string
|
||||
locale map[string]*LDML
|
||||
resolved map[string]*LDML
|
||||
bcp47 *LDMLBCP47
|
||||
supp *SupplementalData
|
||||
}
|
||||
|
||||
func makeCLDR() *CLDR {
|
||||
return &CLDR{
|
||||
parent: make(map[string][]string),
|
||||
locale: make(map[string]*LDML),
|
||||
resolved: make(map[string]*LDML),
|
||||
bcp47: &LDMLBCP47{},
|
||||
supp: &SupplementalData{},
|
||||
}
|
||||
}
|
||||
|
||||
// BCP47 returns the parsed BCP47 LDML data. If no such data was parsed, nil is returned.
|
||||
func (cldr *CLDR) BCP47() *LDMLBCP47 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Draft indicates the draft level of an element.
|
||||
type Draft int
|
||||
|
||||
const (
|
||||
Approved Draft = iota
|
||||
Contributed
|
||||
Provisional
|
||||
Unconfirmed
|
||||
)
|
||||
|
||||
var drafts = []string{"unconfirmed", "provisional", "contributed", "approved", ""}
|
||||
|
||||
// ParseDraft returns the Draft value corresponding to the given string. The
|
||||
// empty string corresponds to Approved.
|
||||
func ParseDraft(level string) (Draft, error) {
|
||||
if level == "" {
|
||||
return Approved, nil
|
||||
}
|
||||
for i, s := range drafts {
|
||||
if level == s {
|
||||
return Unconfirmed - Draft(i), nil
|
||||
}
|
||||
}
|
||||
return Approved, fmt.Errorf("cldr: unknown draft level %q", level)
|
||||
}
|
||||
|
||||
func (d Draft) String() string {
|
||||
return drafts[len(drafts)-1-int(d)]
|
||||
}
|
||||
|
||||
// SetDraftLevel sets which draft levels to include in the evaluated LDML.
|
||||
// Any draft element for which the draft level is higher than lev will be excluded.
|
||||
// If multiple draft levels are available for a single element, the one with the
|
||||
// lowest draft level will be selected, unless preferDraft is true, in which case
|
||||
// the highest draft will be chosen.
|
||||
// It is assumed that the underlying LDML is canonicalized.
|
||||
func (cldr *CLDR) SetDraftLevel(lev Draft, preferDraft bool) {
|
||||
// TODO: implement
|
||||
cldr.resolved = make(map[string]*LDML)
|
||||
}
|
||||
|
||||
// RawLDML returns the LDML XML for id in unresolved form.
|
||||
// id must be one of the strings returned by Locales.
|
||||
func (cldr *CLDR) RawLDML(loc string) *LDML {
|
||||
return cldr.locale[loc]
|
||||
}
|
||||
|
||||
// LDML returns the fully resolved LDML XML for loc, which must be one of
|
||||
// the strings returned by Locales.
|
||||
func (cldr *CLDR) LDML(loc string) (*LDML, error) {
|
||||
return cldr.resolve(loc)
|
||||
}
|
||||
|
||||
// Supplemental returns the parsed supplemental data. If no such data was parsed,
|
||||
// nil is returned.
|
||||
func (cldr *CLDR) Supplemental() *SupplementalData {
|
||||
return cldr.supp
|
||||
}
|
||||
|
||||
// Locales returns the locales for which there exist files.
|
||||
// Valid sublocales for which there is no file are not included.
|
||||
// The root locale is always sorted first.
|
||||
func (cldr *CLDR) Locales() []string {
|
||||
loc := []string{"root"}
|
||||
hasRoot := false
|
||||
for l, _ := range cldr.locale {
|
||||
if l == "root" {
|
||||
hasRoot = true
|
||||
continue
|
||||
}
|
||||
loc = append(loc, l)
|
||||
}
|
||||
sort.Strings(loc[1:])
|
||||
if !hasRoot {
|
||||
return loc[1:]
|
||||
}
|
||||
return loc
|
||||
}
|
||||
|
||||
// Get fills in the fields of x based on the XPath path.
|
||||
func Get(e Elem, path string) (res Elem, err error) {
|
||||
return walkXPath(e, path)
|
||||
}
|
27
vendor/golang.org/x/text/unicode/cldr/cldr_test.go
generated
vendored
Normal file
27
vendor/golang.org/x/text/unicode/cldr/cldr_test.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2014 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
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseDraft(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string
|
||||
draft Draft
|
||||
err bool
|
||||
}{
|
||||
{"unconfirmed", Unconfirmed, false},
|
||||
{"provisional", Provisional, false},
|
||||
{"contributed", Contributed, false},
|
||||
{"approved", Approved, false},
|
||||
{"", Approved, false},
|
||||
{"foo", Approved, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
if d, err := ParseDraft(tt.in); d != tt.draft || (err != nil) != tt.err {
|
||||
t.Errorf("%q: was %v, %v; want %v, %v", tt.in, d, err != nil, tt.draft, tt.err)
|
||||
}
|
||||
}
|
||||
}
|
359
vendor/golang.org/x/text/unicode/cldr/collate.go
generated
vendored
Normal file
359
vendor/golang.org/x/text/unicode/cldr/collate.go
generated
vendored
Normal file
|
@ -0,0 +1,359 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// RuleProcessor can be passed to Collator's Process method, which
|
||||
// parses the rules and calls the respective method for each rule found.
|
||||
type RuleProcessor interface {
|
||||
Reset(anchor string, before int) error
|
||||
Insert(level int, str, context, extend string) error
|
||||
Index(id string)
|
||||
}
|
||||
|
||||
const (
|
||||
// cldrIndex is a Unicode-reserved sentinel value used to mark the start
|
||||
// of a grouping within an index.
|
||||
// We ignore any rule that starts with this rune.
|
||||
// See http://unicode.org/reports/tr35/#Collation_Elements for details.
|
||||
cldrIndex = "\uFDD0"
|
||||
|
||||
// specialAnchor is the format in which to represent logical reset positions,
|
||||
// such as "first tertiary ignorable".
|
||||
specialAnchor = "<%s/>"
|
||||
)
|
||||
|
||||
// Process parses the rules for the tailorings of this collation
|
||||
// and calls the respective methods of p for each rule found.
|
||||
func (c Collation) Process(p RuleProcessor) (err error) {
|
||||
if len(c.Cr) > 0 {
|
||||
if len(c.Cr) > 1 {
|
||||
return fmt.Errorf("multiple cr elements, want 0 or 1")
|
||||
}
|
||||
return processRules(p, c.Cr[0].Data())
|
||||
}
|
||||
if c.Rules.Any != nil {
|
||||
return c.processXML(p)
|
||||
}
|
||||
return errors.New("no tailoring data")
|
||||
}
|
||||
|
||||
// processRules parses rules in the Collation Rule Syntax defined in
|
||||
// http://www.unicode.org/reports/tr35/tr35-collation.html#Collation_Tailorings.
|
||||
func processRules(p RuleProcessor, s string) (err error) {
|
||||
chk := func(s string, e error) string {
|
||||
if err == nil {
|
||||
err = e
|
||||
}
|
||||
return s
|
||||
}
|
||||
i := 0 // Save the line number for use after the loop.
|
||||
scanner := bufio.NewScanner(strings.NewReader(s))
|
||||
for ; scanner.Scan() && err == nil; i++ {
|
||||
for s := skipSpace(scanner.Text()); s != "" && s[0] != '#'; s = skipSpace(s) {
|
||||
level := 5
|
||||
var ch byte
|
||||
switch ch, s = s[0], s[1:]; ch {
|
||||
case '&': // followed by <anchor> or '[' <key> ']'
|
||||
if s = skipSpace(s); consume(&s, '[') {
|
||||
s = chk(parseSpecialAnchor(p, s))
|
||||
} else {
|
||||
s = chk(parseAnchor(p, 0, s))
|
||||
}
|
||||
case '<': // sort relation '<'{1,4}, optionally followed by '*'.
|
||||
for level = 1; consume(&s, '<'); level++ {
|
||||
}
|
||||
if level > 4 {
|
||||
err = fmt.Errorf("level %d > 4", level)
|
||||
}
|
||||
fallthrough
|
||||
case '=': // identity relation, optionally followed by *.
|
||||
if consume(&s, '*') {
|
||||
s = chk(parseSequence(p, level, s))
|
||||
} else {
|
||||
s = chk(parseOrder(p, level, s))
|
||||
}
|
||||
default:
|
||||
chk("", fmt.Errorf("illegal operator %q", ch))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if chk("", scanner.Err()); err != nil {
|
||||
return fmt.Errorf("%d: %v", i, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseSpecialAnchor parses the anchor syntax which is either of the form
|
||||
// ['before' <level>] <anchor>
|
||||
// or
|
||||
// [<label>]
|
||||
// The starting should already be consumed.
|
||||
func parseSpecialAnchor(p RuleProcessor, s string) (tail string, err error) {
|
||||
i := strings.IndexByte(s, ']')
|
||||
if i == -1 {
|
||||
return "", errors.New("unmatched bracket")
|
||||
}
|
||||
a := strings.TrimSpace(s[:i])
|
||||
s = s[i+1:]
|
||||
if strings.HasPrefix(a, "before ") {
|
||||
l, err := strconv.ParseUint(skipSpace(a[len("before "):]), 10, 3)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
return parseAnchor(p, int(l), s)
|
||||
}
|
||||
return s, p.Reset(fmt.Sprintf(specialAnchor, a), 0)
|
||||
}
|
||||
|
||||
func parseAnchor(p RuleProcessor, level int, s string) (tail string, err error) {
|
||||
anchor, s, err := scanString(s)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
return s, p.Reset(anchor, level)
|
||||
}
|
||||
|
||||
func parseOrder(p RuleProcessor, level int, s string) (tail string, err error) {
|
||||
var value, context, extend string
|
||||
if value, s, err = scanString(s); err != nil {
|
||||
return s, err
|
||||
}
|
||||
if strings.HasPrefix(value, cldrIndex) {
|
||||
p.Index(value[len(cldrIndex):])
|
||||
return
|
||||
}
|
||||
if consume(&s, '|') {
|
||||
if context, s, err = scanString(s); err != nil {
|
||||
return s, errors.New("missing string after context")
|
||||
}
|
||||
}
|
||||
if consume(&s, '/') {
|
||||
if extend, s, err = scanString(s); err != nil {
|
||||
return s, errors.New("missing string after extension")
|
||||
}
|
||||
}
|
||||
return s, p.Insert(level, value, context, extend)
|
||||
}
|
||||
|
||||
// scanString scans a single input string.
|
||||
func scanString(s string) (str, tail string, err error) {
|
||||
if s = skipSpace(s); s == "" {
|
||||
return s, s, errors.New("missing string")
|
||||
}
|
||||
buf := [16]byte{} // small but enough to hold most cases.
|
||||
value := buf[:0]
|
||||
for s != "" {
|
||||
if consume(&s, '\'') {
|
||||
i := strings.IndexByte(s, '\'')
|
||||
if i == -1 {
|
||||
return "", "", errors.New(`unmatched single quote`)
|
||||
}
|
||||
if i == 0 {
|
||||
value = append(value, '\'')
|
||||
} else {
|
||||
value = append(value, s[:i]...)
|
||||
}
|
||||
s = s[i+1:]
|
||||
continue
|
||||
}
|
||||
r, sz := utf8.DecodeRuneInString(s)
|
||||
if unicode.IsSpace(r) || strings.ContainsRune("&<=#", r) {
|
||||
break
|
||||
}
|
||||
value = append(value, s[:sz]...)
|
||||
s = s[sz:]
|
||||
}
|
||||
return string(value), skipSpace(s), nil
|
||||
}
|
||||
|
||||
func parseSequence(p RuleProcessor, level int, s string) (tail string, err error) {
|
||||
if s = skipSpace(s); s == "" {
|
||||
return s, errors.New("empty sequence")
|
||||
}
|
||||
last := rune(0)
|
||||
for s != "" {
|
||||
r, sz := utf8.DecodeRuneInString(s)
|
||||
s = s[sz:]
|
||||
|
||||
if r == '-' {
|
||||
// We have a range. The first element was already written.
|
||||
if last == 0 {
|
||||
return s, errors.New("range without starter value")
|
||||
}
|
||||
r, sz = utf8.DecodeRuneInString(s)
|
||||
s = s[sz:]
|
||||
if r == utf8.RuneError || r < last {
|
||||
return s, fmt.Errorf("invalid range %q-%q", last, r)
|
||||
}
|
||||
for i := last + 1; i <= r; i++ {
|
||||
if err := p.Insert(level, string(i), "", ""); err != nil {
|
||||
return s, err
|
||||
}
|
||||
}
|
||||
last = 0
|
||||
continue
|
||||
}
|
||||
|
||||
if unicode.IsSpace(r) || unicode.IsPunct(r) {
|
||||
break
|
||||
}
|
||||
|
||||
// normal case
|
||||
if err := p.Insert(level, string(r), "", ""); err != nil {
|
||||
return s, err
|
||||
}
|
||||
last = r
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func skipSpace(s string) string {
|
||||
return strings.TrimLeftFunc(s, unicode.IsSpace)
|
||||
}
|
||||
|
||||
// consumes returns whether the next byte is ch. If so, it gobbles it by
|
||||
// updating s.
|
||||
func consume(s *string, ch byte) (ok bool) {
|
||||
if *s == "" || (*s)[0] != ch {
|
||||
return false
|
||||
}
|
||||
*s = (*s)[1:]
|
||||
return true
|
||||
}
|
||||
|
||||
// The following code parses Collation rules of CLDR version 24 and before.
|
||||
|
||||
var lmap = map[byte]int{
|
||||
'p': 1,
|
||||
's': 2,
|
||||
't': 3,
|
||||
'i': 5,
|
||||
}
|
||||
|
||||
type rulesElem struct {
|
||||
Rules struct {
|
||||
Common
|
||||
Any []*struct {
|
||||
XMLName xml.Name
|
||||
rule
|
||||
} `xml:",any"`
|
||||
} `xml:"rules"`
|
||||
}
|
||||
|
||||
type rule struct {
|
||||
Value string `xml:",chardata"`
|
||||
Before string `xml:"before,attr"`
|
||||
Any []*struct {
|
||||
XMLName xml.Name
|
||||
rule
|
||||
} `xml:",any"`
|
||||
}
|
||||
|
||||
var emptyValueError = errors.New("cldr: empty rule value")
|
||||
|
||||
func (r *rule) value() (string, error) {
|
||||
// Convert hexadecimal Unicode codepoint notation to a string.
|
||||
s := charRe.ReplaceAllStringFunc(r.Value, replaceUnicode)
|
||||
r.Value = s
|
||||
if s == "" {
|
||||
if len(r.Any) != 1 {
|
||||
return "", emptyValueError
|
||||
}
|
||||
r.Value = fmt.Sprintf(specialAnchor, r.Any[0].XMLName.Local)
|
||||
r.Any = nil
|
||||
} else if len(r.Any) != 0 {
|
||||
return "", fmt.Errorf("cldr: XML elements found in collation rule: %v", r.Any)
|
||||
}
|
||||
return r.Value, nil
|
||||
}
|
||||
|
||||
func (r rule) process(p RuleProcessor, name, context, extend string) error {
|
||||
v, err := r.value()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch name {
|
||||
case "p", "s", "t", "i":
|
||||
if strings.HasPrefix(v, cldrIndex) {
|
||||
p.Index(v[len(cldrIndex):])
|
||||
return nil
|
||||
}
|
||||
if err := p.Insert(lmap[name[0]], v, context, extend); err != nil {
|
||||
return err
|
||||
}
|
||||
case "pc", "sc", "tc", "ic":
|
||||
level := lmap[name[0]]
|
||||
for _, s := range v {
|
||||
if err := p.Insert(level, string(s), context, extend); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("cldr: unsupported tag: %q", name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// processXML parses the format of CLDR versions 24 and older.
|
||||
func (c Collation) processXML(p RuleProcessor) (err error) {
|
||||
// Collation is generated and defined in xml.go.
|
||||
var v string
|
||||
for _, r := range c.Rules.Any {
|
||||
switch r.XMLName.Local {
|
||||
case "reset":
|
||||
level := 0
|
||||
switch r.Before {
|
||||
case "primary", "1":
|
||||
level = 1
|
||||
case "secondary", "2":
|
||||
level = 2
|
||||
case "tertiary", "3":
|
||||
level = 3
|
||||
case "":
|
||||
default:
|
||||
return fmt.Errorf("cldr: unknown level %q", r.Before)
|
||||
}
|
||||
v, err = r.value()
|
||||
if err == nil {
|
||||
err = p.Reset(v, level)
|
||||
}
|
||||
case "x":
|
||||
var context, extend string
|
||||
for _, r1 := range r.Any {
|
||||
v, err = r1.value()
|
||||
switch r1.XMLName.Local {
|
||||
case "context":
|
||||
context = v
|
||||
case "extend":
|
||||
extend = v
|
||||
}
|
||||
}
|
||||
for _, r1 := range r.Any {
|
||||
if t := r1.XMLName.Local; t == "context" || t == "extend" {
|
||||
continue
|
||||
}
|
||||
r1.rule.process(p, r1.XMLName.Local, context, extend)
|
||||
}
|
||||
default:
|
||||
err = r.rule.process(p, r.XMLName.Local, "", "")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
275
vendor/golang.org/x/text/unicode/cldr/collate_test.go
generated
vendored
Normal file
275
vendor/golang.org/x/text/unicode/cldr/collate_test.go
generated
vendored
Normal file
|
@ -0,0 +1,275 @@
|
|||
// Copyright 2014 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// A recorder implements the RuleProcessor interface, whereby its methods
|
||||
// simply record the invocations.
|
||||
type recorder struct {
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (r *recorder) Reset(anchor string, before int) error {
|
||||
if before > 5 {
|
||||
return fmt.Errorf("before %d > 5", before)
|
||||
}
|
||||
r.calls = append(r.calls, fmt.Sprintf("R:%s-%d", anchor, before))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *recorder) Insert(level int, str, context, extend string) error {
|
||||
s := fmt.Sprintf("O:%d:%s", level, str)
|
||||
if context != "" {
|
||||
s += "|" + context
|
||||
}
|
||||
if extend != "" {
|
||||
s += "/" + extend
|
||||
}
|
||||
r.calls = append(r.calls, s)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *recorder) Index(id string) {
|
||||
r.calls = append(r.calls, fmt.Sprintf("I:%s", id))
|
||||
}
|
||||
|
||||
func (r *recorder) Error(err error) {
|
||||
r.calls = append(r.calls, fmt.Sprintf("E:%v", err))
|
||||
}
|
||||
|
||||
func TestRuleProcessor(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
desc string
|
||||
in string
|
||||
out string
|
||||
}{
|
||||
{desc: "empty"},
|
||||
{desc: "whitespace and comments only",
|
||||
in: `
|
||||
|
||||
|
||||
# adsfads
|
||||
# adfadf
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "reset anchor",
|
||||
in: `
|
||||
& a
|
||||
&b #
|
||||
& [ before 3 ] c
|
||||
& [before 4] d & ee
|
||||
& [first tertiary ignorable]
|
||||
&'g'
|
||||
& 'h''h'h'h'
|
||||
&'\u0069' # LATIN SMALL LETTER I
|
||||
`,
|
||||
out: `
|
||||
R:a-0
|
||||
R:b-0
|
||||
R:c-3
|
||||
R:d-4
|
||||
R:ee-0
|
||||
R:<first tertiary ignorable/>-0
|
||||
R:g-0
|
||||
R:hhhh-0
|
||||
R:i-0
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "ordering",
|
||||
in: `
|
||||
& 0
|
||||
< 1 <<''2#
|
||||
<<< 3'3''33'3#
|
||||
<<<<4
|
||||
= 5 << 6 | s
|
||||
<<<< 7 / z
|
||||
<< 8'' | s / ch
|
||||
`,
|
||||
out: `
|
||||
R:0-0
|
||||
O:1:1
|
||||
O:2:'2
|
||||
O:3:33333
|
||||
O:4:4
|
||||
O:5:5
|
||||
O:2:6|s
|
||||
O:4:7/z
|
||||
O:2:8'|s/ch
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "index",
|
||||
in: "< '\ufdd0'A",
|
||||
out: "I:A",
|
||||
},
|
||||
{
|
||||
desc: "sequence",
|
||||
in: `
|
||||
& 0
|
||||
<<* 1234
|
||||
<* a-cde-f
|
||||
=* q-q
|
||||
`,
|
||||
out: `
|
||||
R:0-0
|
||||
O:2:1
|
||||
O:2:2
|
||||
O:2:3
|
||||
O:2:4
|
||||
O:1:a
|
||||
O:1:b
|
||||
O:1:c
|
||||
O:1:d
|
||||
O:1:e
|
||||
O:1:f
|
||||
O:5:q
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "compact",
|
||||
in: "&B<t<<<T<s<<<S<e<<<E",
|
||||
out: `
|
||||
R:B-0
|
||||
O:1:t
|
||||
O:3:T
|
||||
O:1:s
|
||||
O:3:S
|
||||
O:1:e
|
||||
O:3:E
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "err operator",
|
||||
in: "a",
|
||||
out: "E:1: illegal operator 'a'",
|
||||
},
|
||||
{
|
||||
desc: "err line number",
|
||||
in: `& a
|
||||
<< b
|
||||
a`,
|
||||
out: `
|
||||
R:a-0
|
||||
O:2:b
|
||||
E:3: illegal operator 'a'`,
|
||||
},
|
||||
{
|
||||
desc: "err empty anchor",
|
||||
in: " & ",
|
||||
out: "E:1: missing string",
|
||||
},
|
||||
{
|
||||
desc: "err anchor invalid special 1",
|
||||
in: " & [ foo ",
|
||||
out: "E:1: unmatched bracket",
|
||||
},
|
||||
{
|
||||
desc: "err anchor invalid special 2",
|
||||
in: "&[",
|
||||
out: "E:1: unmatched bracket",
|
||||
},
|
||||
{
|
||||
desc: "err anchor invalid before 1",
|
||||
in: "&[before a]",
|
||||
out: `E:1: strconv.ParseUint: parsing "a": invalid syntax`,
|
||||
},
|
||||
{
|
||||
desc: "err anchor invalid before 2",
|
||||
in: "&[before 12]",
|
||||
out: `E:1: strconv.ParseUint: parsing "12": value out of range`,
|
||||
},
|
||||
{
|
||||
desc: "err anchor invalid before 3",
|
||||
in: "&[before 2]",
|
||||
out: "E:1: missing string",
|
||||
},
|
||||
{
|
||||
desc: "err anchor invalid before 4",
|
||||
in: "&[before 6] a",
|
||||
out: "E:1: before 6 > 5",
|
||||
},
|
||||
{
|
||||
desc: "err empty order",
|
||||
in: " < ",
|
||||
out: "E:1: missing string",
|
||||
},
|
||||
{
|
||||
desc: "err empty identity",
|
||||
in: " = ",
|
||||
out: "E:1: missing string",
|
||||
},
|
||||
{
|
||||
desc: "err empty context",
|
||||
in: " < a | ",
|
||||
out: "E:1: missing string after context",
|
||||
},
|
||||
{
|
||||
desc: "err empty extend",
|
||||
in: " < a / ",
|
||||
out: "E:1: missing string after extension",
|
||||
},
|
||||
{
|
||||
desc: "err empty sequence",
|
||||
in: " <* ",
|
||||
out: "E:1: empty sequence",
|
||||
},
|
||||
{
|
||||
desc: "err sequence 1",
|
||||
in: " <* -a",
|
||||
out: "E:1: range without starter value",
|
||||
},
|
||||
{
|
||||
desc: "err sequence 3",
|
||||
in: " <* a-a-b",
|
||||
out: `O:1:a
|
||||
E:1: range without starter value
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "err sequence 3",
|
||||
in: " <* b-a",
|
||||
out: `O:1:b
|
||||
E:1: invalid range 'b'-'a'
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "err unmatched quote",
|
||||
in: " < 'b",
|
||||
out: ` E:1: unmatched single quote
|
||||
`,
|
||||
},
|
||||
} {
|
||||
rec := &recorder{}
|
||||
err := Collation{
|
||||
Cr: []*Common{
|
||||
{hidden: hidden{CharData: tt.in}},
|
||||
},
|
||||
}.Process(rec)
|
||||
if err != nil {
|
||||
rec.Error(err)
|
||||
}
|
||||
got := rec.calls
|
||||
want := strings.Split(strings.TrimSpace(tt.out), "\n")
|
||||
if tt.out == "" {
|
||||
want = nil
|
||||
}
|
||||
if len(got) != len(want) {
|
||||
t.Errorf("%s: nResults: got %d; want %d", tt.desc, len(got), len(want))
|
||||
continue
|
||||
}
|
||||
for i, g := range got {
|
||||
if want := strings.TrimSpace(want[i]); g != want {
|
||||
t.Errorf("%s:%d: got %q; want %q", tt.desc, i, g, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
186
vendor/golang.org/x/text/unicode/cldr/data_test.go
generated
vendored
Normal file
186
vendor/golang.org/x/text/unicode/cldr/data_test.go
generated
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
// 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 contains test data.
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type testLoader struct {
|
||||
}
|
||||
|
||||
func (t testLoader) Len() int {
|
||||
return len(testFiles)
|
||||
}
|
||||
|
||||
func (t testLoader) Path(i int) string {
|
||||
return testPaths[i]
|
||||
}
|
||||
|
||||
func (t testLoader) Reader(i int) (io.ReadCloser, error) {
|
||||
return &reader{*strings.NewReader(testFiles[i])}, nil
|
||||
}
|
||||
|
||||
// reader adds a dummy Close method to strings.Reader so that it
|
||||
// satisfies the io.ReadCloser interface.
|
||||
type reader struct {
|
||||
strings.Reader
|
||||
}
|
||||
|
||||
func (r reader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
testFiles = []string{de_xml, gsw_xml, root_xml}
|
||||
testPaths = []string{
|
||||
"common/main/de.xml",
|
||||
"common/main/gsw.xml",
|
||||
"common/main/root.xml",
|
||||
}
|
||||
)
|
||||
|
||||
var root_xml = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE ldml SYSTEM "../../common/dtd/ldml.dtd">
|
||||
<ldml>
|
||||
<identity>
|
||||
<language type="root"/>
|
||||
<generation date="now"/>
|
||||
</identity>
|
||||
<characters>
|
||||
<exemplarCharacters>[]</exemplarCharacters>
|
||||
<exemplarCharacters type="auxiliary">[]</exemplarCharacters>
|
||||
<exemplarCharacters type="punctuation">[\- ‐ – — … ' ‘ ‚ " “ „ \& #]</exemplarCharacters>
|
||||
<ellipsis type="final">{0}…</ellipsis>
|
||||
<ellipsis type="initial">…{0}</ellipsis>
|
||||
<moreInformation>?</moreInformation>
|
||||
</characters>
|
||||
<dates>
|
||||
<calendars>
|
||||
<default choice="gregorian"/>
|
||||
<calendar type="buddhist">
|
||||
<months>
|
||||
<alias source="locale" path="../../calendar[@type='gregorian']/months"/>
|
||||
</months>
|
||||
</calendar>
|
||||
<calendar type="chinese">
|
||||
<months>
|
||||
<alias source="locale" path="../../calendar[@type='gregorian']/months"/>
|
||||
</months>
|
||||
</calendar>
|
||||
<calendar type="gregorian">
|
||||
<months>
|
||||
<default choice="format"/>
|
||||
<monthContext type="format">
|
||||
<default choice="wide"/>
|
||||
<monthWidth type="narrow">
|
||||
<alias source="locale" path="../../monthContext[@type='stand-alone']/monthWidth[@type='narrow']"/>
|
||||
</monthWidth>
|
||||
<monthWidth type="wide">
|
||||
<month type="1">11</month>
|
||||
<month type="2">22</month>
|
||||
<month type="3">33</month>
|
||||
<month type="4">44</month>
|
||||
</monthWidth>
|
||||
</monthContext>
|
||||
<monthContext type="stand-alone">
|
||||
<monthWidth type="narrow">
|
||||
<month type="1">1</month>
|
||||
<month type="2">2</month>
|
||||
<month type="3">3</month>
|
||||
<month type="4">4</month>
|
||||
</monthWidth>
|
||||
<monthWidth type="wide">
|
||||
<alias source="locale" path="../../monthContext[@type='format']/monthWidth[@type='wide']"/>
|
||||
</monthWidth>
|
||||
</monthContext>
|
||||
</months>
|
||||
</calendar>
|
||||
</calendars>
|
||||
</dates>
|
||||
</ldml>
|
||||
`
|
||||
|
||||
var de_xml = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE ldml SYSTEM "../../common/dtd/ldml.dtd">
|
||||
<ldml>
|
||||
<identity>
|
||||
<language type="de"/>
|
||||
</identity>
|
||||
<characters>
|
||||
<exemplarCharacters>[a ä b c d e ö p q r s ß t u ü v w x y z]</exemplarCharacters>
|
||||
<exemplarCharacters type="auxiliary">[á à ă]</exemplarCharacters>
|
||||
<exemplarCharacters type="index">[A B C D E F G H Z]</exemplarCharacters>
|
||||
<ellipsis type="final">{0} …</ellipsis>
|
||||
<ellipsis type="initial">… {0}</ellipsis>
|
||||
<moreInformation>?</moreInformation>
|
||||
<stopwords>
|
||||
<stopwordList type="collation" draft="provisional">der die das</stopwordList>
|
||||
</stopwords>
|
||||
</characters>
|
||||
<dates>
|
||||
<calendars>
|
||||
<calendar type="buddhist">
|
||||
<months>
|
||||
<monthContext type="format">
|
||||
<monthWidth type="narrow">
|
||||
<month type="3">BBB</month>
|
||||
</monthWidth>
|
||||
<monthWidth type="wide">
|
||||
<month type="3">bbb</month>
|
||||
</monthWidth>
|
||||
</monthContext>
|
||||
</months>
|
||||
</calendar>
|
||||
<calendar type="gregorian">
|
||||
<months>
|
||||
<monthContext type="format">
|
||||
<monthWidth type="narrow">
|
||||
<month type="3">M</month>
|
||||
<month type="4">A</month>
|
||||
</monthWidth>
|
||||
<monthWidth type="wide">
|
||||
<month type="3">Maerz</month>
|
||||
<month type="4">April</month>
|
||||
<month type="5">Mai</month>
|
||||
</monthWidth>
|
||||
</monthContext>
|
||||
<monthContext type="stand-alone">
|
||||
<monthWidth type="narrow">
|
||||
<month type="3">m</month>
|
||||
<month type="5">m</month>
|
||||
</monthWidth>
|
||||
<monthWidth type="wide">
|
||||
<month type="4">april</month>
|
||||
<month type="5">mai</month>
|
||||
</monthWidth>
|
||||
</monthContext>
|
||||
</months>
|
||||
</calendar>
|
||||
</calendars>
|
||||
</dates>
|
||||
<posix>
|
||||
<messages>
|
||||
<yesstr>yes:y</yesstr>
|
||||
<nostr>no:n</nostr>
|
||||
</messages>
|
||||
</posix>
|
||||
</ldml>
|
||||
`
|
||||
|
||||
var gsw_xml = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE ldml SYSTEM "../../common/dtd/ldml.dtd">
|
||||
<ldml>
|
||||
<identity>
|
||||
<language type="gsw"/>
|
||||
</identity>
|
||||
<posix>
|
||||
<alias source="de" path="//ldml/posix"/>
|
||||
</posix>
|
||||
</ldml>
|
||||
`
|
171
vendor/golang.org/x/text/unicode/cldr/decode.go
generated
vendored
Normal file
171
vendor/golang.org/x/text/unicode/cldr/decode.go
generated
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// A Decoder loads an archive of CLDR data.
|
||||
type Decoder struct {
|
||||
dirFilter []string
|
||||
sectionFilter []string
|
||||
loader Loader
|
||||
cldr *CLDR
|
||||
curLocale string
|
||||
}
|
||||
|
||||
// SetSectionFilter takes a list top-level LDML element names to which
|
||||
// evaluation of LDML should be limited. It automatically calls SetDirFilter.
|
||||
func (d *Decoder) SetSectionFilter(filter ...string) {
|
||||
d.sectionFilter = filter
|
||||
// TODO: automatically set dir filter
|
||||
}
|
||||
|
||||
// SetDirFilter limits the loading of LDML XML files of the specied directories.
|
||||
// Note that sections may be split across directories differently for different CLDR versions.
|
||||
// For more robust code, use SetSectionFilter.
|
||||
func (d *Decoder) SetDirFilter(dir ...string) {
|
||||
d.dirFilter = dir
|
||||
}
|
||||
|
||||
// A Loader provides access to the files of a CLDR archive.
|
||||
type Loader interface {
|
||||
Len() int
|
||||
Path(i int) string
|
||||
Reader(i int) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
var fileRe = regexp.MustCompile(`.*[/\\](.*)[/\\](.*)\.xml`)
|
||||
|
||||
// Decode loads and decodes the files represented by l.
|
||||
func (d *Decoder) Decode(l Loader) (cldr *CLDR, err error) {
|
||||
d.cldr = makeCLDR()
|
||||
for i := 0; i < l.Len(); i++ {
|
||||
fname := l.Path(i)
|
||||
if m := fileRe.FindStringSubmatch(fname); m != nil {
|
||||
if len(d.dirFilter) > 0 && !in(d.dirFilter, m[1]) {
|
||||
continue
|
||||
}
|
||||
var r io.Reader
|
||||
if r, err = l.Reader(i); err == nil {
|
||||
err = d.decode(m[1], m[2], r)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
d.cldr.finalize(d.sectionFilter)
|
||||
return d.cldr, nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decode(dir, id string, r io.Reader) error {
|
||||
var v interface{}
|
||||
var l *LDML
|
||||
cldr := d.cldr
|
||||
switch {
|
||||
case dir == "supplemental":
|
||||
v = cldr.supp
|
||||
case dir == "transforms":
|
||||
return nil
|
||||
case dir == "bcp47":
|
||||
v = cldr.bcp47
|
||||
case dir == "validity":
|
||||
return nil
|
||||
default:
|
||||
ok := false
|
||||
if v, ok = cldr.locale[id]; !ok {
|
||||
l = &LDML{}
|
||||
v, cldr.locale[id] = l, l
|
||||
}
|
||||
}
|
||||
x := xml.NewDecoder(r)
|
||||
if err := x.Decode(v); err != nil {
|
||||
log.Printf("%s/%s: %v", dir, id, err)
|
||||
return err
|
||||
}
|
||||
if l != nil {
|
||||
if l.Identity == nil {
|
||||
return fmt.Errorf("%s/%s: missing identity element", dir, id)
|
||||
}
|
||||
// TODO: verify when CLDR bug http://unicode.org/cldr/trac/ticket/8970
|
||||
// is resolved.
|
||||
// path := strings.Split(id, "_")
|
||||
// if lang := l.Identity.Language.Type; lang != path[0] {
|
||||
// return fmt.Errorf("%s/%s: language was %s; want %s", dir, id, lang, path[0])
|
||||
// }
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type pathLoader []string
|
||||
|
||||
func makePathLoader(path string) (pl pathLoader, err error) {
|
||||
err = filepath.Walk(path, func(path string, _ os.FileInfo, err error) error {
|
||||
pl = append(pl, path)
|
||||
return err
|
||||
})
|
||||
return pl, err
|
||||
}
|
||||
|
||||
func (pl pathLoader) Len() int {
|
||||
return len(pl)
|
||||
}
|
||||
|
||||
func (pl pathLoader) Path(i int) string {
|
||||
return pl[i]
|
||||
}
|
||||
|
||||
func (pl pathLoader) Reader(i int) (io.ReadCloser, error) {
|
||||
return os.Open(pl[i])
|
||||
}
|
||||
|
||||
// DecodePath loads CLDR data from the given path.
|
||||
func (d *Decoder) DecodePath(path string) (cldr *CLDR, err error) {
|
||||
loader, err := makePathLoader(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.Decode(loader)
|
||||
}
|
||||
|
||||
type zipLoader struct {
|
||||
r *zip.Reader
|
||||
}
|
||||
|
||||
func (zl zipLoader) Len() int {
|
||||
return len(zl.r.File)
|
||||
}
|
||||
|
||||
func (zl zipLoader) Path(i int) string {
|
||||
return zl.r.File[i].Name
|
||||
}
|
||||
|
||||
func (zl zipLoader) Reader(i int) (io.ReadCloser, error) {
|
||||
return zl.r.File[i].Open()
|
||||
}
|
||||
|
||||
// DecodeZip loads CLDR data from the zip archive for which r is the source.
|
||||
func (d *Decoder) DecodeZip(r io.Reader) (cldr *CLDR, err error) {
|
||||
buffer, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return d.Decode(zipLoader{archive})
|
||||
}
|
21
vendor/golang.org/x/text/unicode/cldr/examples_test.go
generated
vendored
Normal file
21
vendor/golang.org/x/text/unicode/cldr/examples_test.go
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
package cldr_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/text/unicode/cldr"
|
||||
)
|
||||
|
||||
func ExampleSlice() {
|
||||
var dr *cldr.CLDR // assume this is initialized
|
||||
|
||||
x, _ := dr.LDML("en")
|
||||
cs := x.Collations.Collation
|
||||
// remove all but the default
|
||||
cldr.MakeSlice(&cs).Filter(func(e cldr.Elem) bool {
|
||||
return e.GetCommon().Type != x.Collations.Default()
|
||||
})
|
||||
for i, c := range cs {
|
||||
fmt.Println(i, c.Type)
|
||||
}
|
||||
}
|
400
vendor/golang.org/x/text/unicode/cldr/makexml.go
generated
vendored
Normal file
400
vendor/golang.org/x/text/unicode/cldr/makexml.go
generated
vendored
Normal file
|
@ -0,0 +1,400 @@
|
|||
// 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.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This tool generates types for the various XML formats of CLDR.
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"encoding/xml"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/internal/gen"
|
||||
)
|
||||
|
||||
var outputFile = flag.String("output", "xml.go", "output file name")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
r := gen.OpenCLDRCoreZip()
|
||||
buffer, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
log.Fatal("Could not read zip file")
|
||||
}
|
||||
r.Close()
|
||||
z, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read zip archive: %v", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
version := gen.CLDRVersion()
|
||||
|
||||
for _, dtd := range files {
|
||||
for _, f := range z.File {
|
||||
if strings.HasSuffix(f.Name, dtd.file+".dtd") {
|
||||
r, err := f.Open()
|
||||
failOnError(err)
|
||||
|
||||
b := makeBuilder(&buf, dtd)
|
||||
b.parseDTD(r)
|
||||
b.resolve(b.index[dtd.top[0]])
|
||||
b.write()
|
||||
if b.version != "" && version != b.version {
|
||||
println(f.Name)
|
||||
log.Fatalf("main: inconsistent versions: found %s; want %s", b.version, version)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(&buf, "// Version is the version of CLDR from which the XML definitions are generated.")
|
||||
fmt.Fprintf(&buf, "const Version = %q\n", version)
|
||||
|
||||
gen.WriteGoFile(*outputFile, "cldr", buf.Bytes())
|
||||
}
|
||||
|
||||
func failOnError(err error) {
|
||||
if err != nil {
|
||||
log.New(os.Stderr, "", log.Lshortfile).Output(2, err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// configuration data per DTD type
|
||||
type dtd struct {
|
||||
file string // base file name
|
||||
root string // Go name of the root XML element
|
||||
top []string // create a different type for this section
|
||||
|
||||
skipElem []string // hard-coded or deprecated elements
|
||||
skipAttr []string // attributes to exclude
|
||||
predefined []string // hard-coded elements exist of the form <name>Elem
|
||||
forceRepeat []string // elements to make slices despite DTD
|
||||
}
|
||||
|
||||
var files = []dtd{
|
||||
{
|
||||
file: "ldmlBCP47",
|
||||
root: "LDMLBCP47",
|
||||
top: []string{"ldmlBCP47"},
|
||||
skipElem: []string{
|
||||
"cldrVersion", // deprecated, not used
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "ldmlSupplemental",
|
||||
root: "SupplementalData",
|
||||
top: []string{"supplementalData"},
|
||||
skipElem: []string{
|
||||
"cldrVersion", // deprecated, not used
|
||||
},
|
||||
forceRepeat: []string{
|
||||
"plurals", // data defined in plurals.xml and ordinals.xml
|
||||
},
|
||||
},
|
||||
{
|
||||
file: "ldml",
|
||||
root: "LDML",
|
||||
top: []string{
|
||||
"ldml", "collation", "calendar", "timeZoneNames", "localeDisplayNames", "numbers",
|
||||
},
|
||||
skipElem: []string{
|
||||
"cp", // not used anywhere
|
||||
"special", // not used anywhere
|
||||
"fallback", // deprecated, not used
|
||||
"alias", // in Common
|
||||
"default", // in Common
|
||||
},
|
||||
skipAttr: []string{
|
||||
"hiraganaQuarternary", // typo in DTD, correct version included as well
|
||||
},
|
||||
predefined: []string{"rules"},
|
||||
},
|
||||
}
|
||||
|
||||
var comments = map[string]string{
|
||||
"ldmlBCP47": `
|
||||
// LDMLBCP47 holds information on allowable values for various variables in LDML.
|
||||
`,
|
||||
"supplementalData": `
|
||||
// SupplementalData holds information relevant for internationalization
|
||||
// and proper use of CLDR, but that is not contained in the locale hierarchy.
|
||||
`,
|
||||
"ldml": `
|
||||
// LDML is the top-level type for locale-specific data.
|
||||
`,
|
||||
"collation": `
|
||||
// Collation contains rules that specify a certain sort-order,
|
||||
// as a tailoring of the root order.
|
||||
// The parsed rules are obtained by passing a RuleProcessor to Collation's
|
||||
// Process method.
|
||||
`,
|
||||
"calendar": `
|
||||
// Calendar specifies the fields used for formatting and parsing dates and times.
|
||||
// The month and quarter names are identified numerically, starting at 1.
|
||||
// The day (of the week) names are identified with short strings, since there is
|
||||
// no universally-accepted numeric designation.
|
||||
`,
|
||||
"dates": `
|
||||
// Dates contains information regarding the format and parsing of dates and times.
|
||||
`,
|
||||
"localeDisplayNames": `
|
||||
// LocaleDisplayNames specifies localized display names for for scripts, languages,
|
||||
// countries, currencies, and variants.
|
||||
`,
|
||||
"numbers": `
|
||||
// Numbers supplies information for formatting and parsing numbers and currencies.
|
||||
`,
|
||||
}
|
||||
|
||||
type element struct {
|
||||
name string // XML element name
|
||||
category string // elements contained by this element
|
||||
signature string // category + attrKey*
|
||||
|
||||
attr []*attribute // attributes supported by this element.
|
||||
sub []struct { // parsed and evaluated sub elements of this element.
|
||||
e *element
|
||||
repeat bool // true if the element needs to be a slice
|
||||
}
|
||||
|
||||
resolved bool // prevent multiple resolutions of this element.
|
||||
}
|
||||
|
||||
type attribute struct {
|
||||
name string
|
||||
key string
|
||||
list []string
|
||||
|
||||
tag string // Go tag
|
||||
}
|
||||
|
||||
var (
|
||||
reHead = regexp.MustCompile(` *(\w+) +([\w\-]+)`)
|
||||
reAttr = regexp.MustCompile(` *(\w+) *(?:(\w+)|\(([\w\- \|]+)\)) *(?:#([A-Z]*) *(?:\"([\.\d+])\")?)? *("[\w\-:]*")?`)
|
||||
reElem = regexp.MustCompile(`^ *(EMPTY|ANY|\(.*\)[\*\+\?]?) *$`)
|
||||
reToken = regexp.MustCompile(`\w\-`)
|
||||
)
|
||||
|
||||
// builder is used to read in the DTD files from CLDR and generate Go code
|
||||
// to be used with the encoding/xml package.
|
||||
type builder struct {
|
||||
w io.Writer
|
||||
index map[string]*element
|
||||
elem []*element
|
||||
info dtd
|
||||
version string
|
||||
}
|
||||
|
||||
func makeBuilder(w io.Writer, d dtd) builder {
|
||||
return builder{
|
||||
w: w,
|
||||
index: make(map[string]*element),
|
||||
elem: []*element{},
|
||||
info: d,
|
||||
}
|
||||
}
|
||||
|
||||
// parseDTD parses a DTD file.
|
||||
func (b *builder) parseDTD(r io.Reader) {
|
||||
for d := xml.NewDecoder(r); ; {
|
||||
t, err := d.Token()
|
||||
if t == nil {
|
||||
break
|
||||
}
|
||||
failOnError(err)
|
||||
dir, ok := t.(xml.Directive)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
m := reHead.FindSubmatch(dir)
|
||||
dir = dir[len(m[0]):]
|
||||
ename := string(m[2])
|
||||
el, elementFound := b.index[ename]
|
||||
switch string(m[1]) {
|
||||
case "ELEMENT":
|
||||
if elementFound {
|
||||
log.Fatal("parseDTD: duplicate entry for element %q", ename)
|
||||
}
|
||||
m := reElem.FindSubmatch(dir)
|
||||
if m == nil {
|
||||
log.Fatalf("parseDTD: invalid element %q", string(dir))
|
||||
}
|
||||
if len(m[0]) != len(dir) {
|
||||
log.Fatal("parseDTD: invalid element %q", string(dir), len(dir), len(m[0]), string(m[0]))
|
||||
}
|
||||
s := string(m[1])
|
||||
el = &element{
|
||||
name: ename,
|
||||
category: s,
|
||||
}
|
||||
b.index[ename] = el
|
||||
case "ATTLIST":
|
||||
if !elementFound {
|
||||
log.Fatalf("parseDTD: unknown element %q", ename)
|
||||
}
|
||||
s := string(dir)
|
||||
m := reAttr.FindStringSubmatch(s)
|
||||
if m == nil {
|
||||
log.Fatal(fmt.Errorf("parseDTD: invalid attribute %q", string(dir)))
|
||||
}
|
||||
if m[4] == "FIXED" {
|
||||
b.version = m[5]
|
||||
} else {
|
||||
switch m[1] {
|
||||
case "draft", "references", "alt", "validSubLocales", "standard" /* in Common */ :
|
||||
case "type", "choice":
|
||||
default:
|
||||
el.attr = append(el.attr, &attribute{
|
||||
name: m[1],
|
||||
key: s,
|
||||
list: reToken.FindAllString(m[3], -1),
|
||||
})
|
||||
el.signature = fmt.Sprintf("%s=%s+%s", el.signature, m[1], m[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var reCat = regexp.MustCompile(`[ ,\|]*(?:(\(|\)|\#?[\w_-]+)([\*\+\?]?))?`)
|
||||
|
||||
// resolve takes a parsed element and converts it into structured data
|
||||
// that can be used to generate the XML code.
|
||||
func (b *builder) resolve(e *element) {
|
||||
if e.resolved {
|
||||
return
|
||||
}
|
||||
b.elem = append(b.elem, e)
|
||||
e.resolved = true
|
||||
s := e.category
|
||||
found := make(map[string]bool)
|
||||
sequenceStart := []int{}
|
||||
for len(s) > 0 {
|
||||
m := reCat.FindStringSubmatch(s)
|
||||
if m == nil {
|
||||
log.Fatalf("%s: invalid category string %q", e.name, s)
|
||||
}
|
||||
repeat := m[2] == "*" || m[2] == "+" || in(b.info.forceRepeat, m[1])
|
||||
switch m[1] {
|
||||
case "":
|
||||
case "(":
|
||||
sequenceStart = append(sequenceStart, len(e.sub))
|
||||
case ")":
|
||||
if len(sequenceStart) == 0 {
|
||||
log.Fatalf("%s: unmatched closing parenthesis", e.name)
|
||||
}
|
||||
for i := sequenceStart[len(sequenceStart)-1]; i < len(e.sub); i++ {
|
||||
e.sub[i].repeat = e.sub[i].repeat || repeat
|
||||
}
|
||||
sequenceStart = sequenceStart[:len(sequenceStart)-1]
|
||||
default:
|
||||
if in(b.info.skipElem, m[1]) {
|
||||
} else if sub, ok := b.index[m[1]]; ok {
|
||||
if !found[sub.name] {
|
||||
e.sub = append(e.sub, struct {
|
||||
e *element
|
||||
repeat bool
|
||||
}{sub, repeat})
|
||||
found[sub.name] = true
|
||||
b.resolve(sub)
|
||||
}
|
||||
} else if m[1] == "#PCDATA" || m[1] == "ANY" {
|
||||
} else if m[1] != "EMPTY" {
|
||||
log.Fatalf("resolve:%s: element %q not found", e.name, m[1])
|
||||
}
|
||||
}
|
||||
s = s[len(m[0]):]
|
||||
}
|
||||
}
|
||||
|
||||
// return true if s is contained in set.
|
||||
func in(set []string, s string) bool {
|
||||
for _, v := range set {
|
||||
if v == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var repl = strings.NewReplacer("-", " ", "_", " ")
|
||||
|
||||
// title puts the first character or each character following '_' in title case and
|
||||
// removes all occurrences of '_'.
|
||||
func title(s string) string {
|
||||
return strings.Replace(strings.Title(repl.Replace(s)), " ", "", -1)
|
||||
}
|
||||
|
||||
// writeElem generates Go code for a single element, recursively.
|
||||
func (b *builder) writeElem(tab int, e *element) {
|
||||
p := func(f string, x ...interface{}) {
|
||||
f = strings.Replace(f, "\n", "\n"+strings.Repeat("\t", tab), -1)
|
||||
fmt.Fprintf(b.w, f, x...)
|
||||
}
|
||||
if len(e.sub) == 0 && len(e.attr) == 0 {
|
||||
p("Common")
|
||||
return
|
||||
}
|
||||
p("struct {")
|
||||
tab++
|
||||
p("\nCommon")
|
||||
for _, attr := range e.attr {
|
||||
if !in(b.info.skipAttr, attr.name) {
|
||||
p("\n%s string `xml:\"%s,attr\"`", title(attr.name), attr.name)
|
||||
}
|
||||
}
|
||||
for _, sub := range e.sub {
|
||||
if in(b.info.predefined, sub.e.name) {
|
||||
p("\n%sElem", sub.e.name)
|
||||
continue
|
||||
}
|
||||
if in(b.info.skipElem, sub.e.name) {
|
||||
continue
|
||||
}
|
||||
p("\n%s ", title(sub.e.name))
|
||||
if sub.repeat {
|
||||
p("[]")
|
||||
}
|
||||
p("*")
|
||||
if in(b.info.top, sub.e.name) {
|
||||
p(title(sub.e.name))
|
||||
} else {
|
||||
b.writeElem(tab, sub.e)
|
||||
}
|
||||
p(" `xml:\"%s\"`", sub.e.name)
|
||||
}
|
||||
tab--
|
||||
p("\n}")
|
||||
}
|
||||
|
||||
// write generates the Go XML code.
|
||||
func (b *builder) write() {
|
||||
for i, name := range b.info.top {
|
||||
e := b.index[name]
|
||||
if e != nil {
|
||||
fmt.Fprintf(b.w, comments[name])
|
||||
name := title(e.name)
|
||||
if i == 0 {
|
||||
name = b.info.root
|
||||
}
|
||||
fmt.Fprintf(b.w, "type %s ", name)
|
||||
b.writeElem(0, e)
|
||||
fmt.Fprint(b.w, "\n")
|
||||
}
|
||||
}
|
||||
}
|
602
vendor/golang.org/x/text/unicode/cldr/resolve.go
generated
vendored
Normal file
602
vendor/golang.org/x/text/unicode/cldr/resolve.go
generated
vendored
Normal file
|
@ -0,0 +1,602 @@
|
|||
// 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")
|
||||
}
|
||||
}
|
368
vendor/golang.org/x/text/unicode/cldr/resolve_test.go
generated
vendored
Normal file
368
vendor/golang.org/x/text/unicode/cldr/resolve_test.go
generated
vendored
Normal file
|
@ -0,0 +1,368 @@
|
|||
package cldr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func failOnError(err error) {
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func data() *CLDR {
|
||||
d := Decoder{}
|
||||
data, err := d.Decode(testLoader{})
|
||||
failOnError(err)
|
||||
return data
|
||||
}
|
||||
|
||||
type h struct {
|
||||
A string `xml:"ha,attr"`
|
||||
E string `xml:"he"`
|
||||
D string `xml:",chardata"`
|
||||
X string
|
||||
}
|
||||
|
||||
type fieldTest struct {
|
||||
Common
|
||||
To string `xml:"to,attr"`
|
||||
Key string `xml:"key,attr"`
|
||||
E string `xml:"e"`
|
||||
D string `xml:",chardata"`
|
||||
X string
|
||||
h
|
||||
}
|
||||
|
||||
var testStruct = fieldTest{
|
||||
Common: Common{
|
||||
name: "mapping", // exclude "type" as distinguishing attribute
|
||||
Type: "foo",
|
||||
Alt: "foo",
|
||||
},
|
||||
To: "nyc",
|
||||
Key: "k",
|
||||
E: "E",
|
||||
D: "D",
|
||||
h: h{
|
||||
A: "A",
|
||||
E: "E",
|
||||
D: "D",
|
||||
},
|
||||
}
|
||||
|
||||
func TestIter(t *testing.T) {
|
||||
tests := map[string]string{
|
||||
"Type": "foo",
|
||||
"Alt": "foo",
|
||||
"To": "nyc",
|
||||
"A": "A",
|
||||
"Alias": "<nil>",
|
||||
}
|
||||
k := 0
|
||||
for i := iter(reflect.ValueOf(testStruct)); !i.done(); i.next() {
|
||||
v := i.value()
|
||||
if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.String {
|
||||
v = v.Elem()
|
||||
}
|
||||
name := i.field().Name
|
||||
if w, ok := tests[name]; ok {
|
||||
s := fmt.Sprint(v.Interface())
|
||||
if w != s {
|
||||
t.Errorf("value: found %q; want %q", w, s)
|
||||
}
|
||||
delete(tests, name)
|
||||
}
|
||||
k++
|
||||
}
|
||||
if len(tests) != 0 {
|
||||
t.Errorf("missing fields: %v", tests)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindField(t *testing.T) {
|
||||
tests := []struct {
|
||||
name, val string
|
||||
exist bool
|
||||
}{
|
||||
{"type", "foo", true},
|
||||
{"alt", "foo", true},
|
||||
{"to", "nyc", true},
|
||||
{"he", "E", true},
|
||||
{"q", "", false},
|
||||
}
|
||||
vf := reflect.ValueOf(testStruct)
|
||||
for i, tt := range tests {
|
||||
v, err := findField(vf, tt.name)
|
||||
if (err == nil) != tt.exist {
|
||||
t.Errorf("%d: field %q present is %v; want %v", i, tt.name, err == nil, tt.exist)
|
||||
} else if tt.exist {
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
continue
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.String() != tt.val {
|
||||
t.Errorf("%d: found value %q; want %q", i, v.String(), tt.val)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var keyTests = []struct {
|
||||
exclude []string
|
||||
key string
|
||||
}{
|
||||
{[]string{}, "alt=foo;key=k;to=nyc"},
|
||||
{[]string{"type"}, "alt=foo;key=k;to=nyc"},
|
||||
{[]string{"choice"}, "alt=foo;key=k;to=nyc"},
|
||||
{[]string{"alt"}, "key=k;to=nyc"},
|
||||
{[]string{"a"}, "alt=foo;key=k;to=nyc"},
|
||||
{[]string{"to"}, "alt=foo;key=k"},
|
||||
{[]string{"alt", "to"}, "key=k"},
|
||||
{[]string{"alt", "to", "key"}, ""},
|
||||
}
|
||||
|
||||
func TestAttrKey(t *testing.T) {
|
||||
v := reflect.ValueOf(&testStruct)
|
||||
for i, tt := range keyTests {
|
||||
key := attrKey(v, tt.exclude...)
|
||||
if key != tt.key {
|
||||
t.Errorf("%d: found %q, want %q", i, key, tt.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKey(t *testing.T) {
|
||||
for i, tt := range keyTests {
|
||||
key := Key(&testStruct, tt.exclude...)
|
||||
if key != tt.key {
|
||||
t.Errorf("%d: found %q, want %q", i, key, tt.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testEnclosing(t *testing.T, x *LDML, name string) {
|
||||
eq := func(a, b Elem, i int) {
|
||||
for ; i > 0; i-- {
|
||||
b = b.enclosing()
|
||||
}
|
||||
if a != b {
|
||||
t.Errorf("%s: found path %q, want %q", name, getPath(a), getPath(b))
|
||||
}
|
||||
}
|
||||
eq(x, x, 0)
|
||||
eq(x, x.Identity, 1)
|
||||
eq(x, x.Dates.Calendars, 2)
|
||||
eq(x, x.Dates.Calendars.Calendar[0], 3)
|
||||
eq(x, x.Dates.Calendars.Calendar[1], 3)
|
||||
//eq(x, x.Dates.Calendars.Calendar[0].Months, 4)
|
||||
eq(x, x.Dates.Calendars.Calendar[1].Months, 4)
|
||||
}
|
||||
|
||||
func TestEnclosing(t *testing.T) {
|
||||
testEnclosing(t, data().RawLDML("de"), "enclosing-raw")
|
||||
de, _ := data().LDML("de")
|
||||
testEnclosing(t, de, "enclosing")
|
||||
}
|
||||
|
||||
func TestDeepCopy(t *testing.T) {
|
||||
eq := func(have, want string) {
|
||||
if have != want {
|
||||
t.Errorf("found %q; want %q", have, want)
|
||||
}
|
||||
}
|
||||
x, _ := data().LDML("de")
|
||||
vc := deepCopy(reflect.ValueOf(x))
|
||||
c := vc.Interface().(*LDML)
|
||||
linkEnclosing(nil, c)
|
||||
if x == c {
|
||||
t.Errorf("did not copy")
|
||||
}
|
||||
|
||||
eq(c.name, "ldml")
|
||||
eq(c.Dates.name, "dates")
|
||||
testEnclosing(t, c, "deepCopy")
|
||||
}
|
||||
|
||||
type getTest struct {
|
||||
loc string
|
||||
path string
|
||||
field string // used in combination with length
|
||||
data string
|
||||
altData string // used for buddhist calendar if value != ""
|
||||
typ string
|
||||
length int
|
||||
missing bool
|
||||
}
|
||||
|
||||
const (
|
||||
budMon = "dates/calendars/calendar[@type='buddhist']/months/"
|
||||
chnMon = "dates/calendars/calendar[@type='chinese']/months/"
|
||||
greMon = "dates/calendars/calendar[@type='gregorian']/months/"
|
||||
)
|
||||
|
||||
func monthVal(path, context, width string, month int) string {
|
||||
const format = "%s/monthContext[@type='%s']/monthWidth[@type='%s']/month[@type='%d']"
|
||||
return fmt.Sprintf(format, path, context, width, month)
|
||||
}
|
||||
|
||||
var rootGetTests = []getTest{
|
||||
{loc: "root", path: "identity/language", typ: "root"},
|
||||
{loc: "root", path: "characters/moreInformation", data: "?"},
|
||||
{loc: "root", path: "characters", field: "exemplarCharacters", length: 3},
|
||||
{loc: "root", path: greMon, field: "monthContext", length: 2},
|
||||
{loc: "root", path: greMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4},
|
||||
{loc: "root", path: greMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4},
|
||||
// unescaping character data
|
||||
{loc: "root", path: "characters/exemplarCharacters[@type='punctuation']", data: `[\- ‐ – — … ' ‘ ‚ " “ „ \& #]`},
|
||||
// default resolution
|
||||
{loc: "root", path: "dates/calendars/calendar", typ: "gregorian"},
|
||||
// alias resolution
|
||||
{loc: "root", path: budMon, field: "monthContext", length: 2},
|
||||
// crossing but non-circular alias resolution
|
||||
{loc: "root", path: budMon + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 4},
|
||||
{loc: "root", path: budMon + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 4},
|
||||
{loc: "root", path: monthVal(greMon, "format", "wide", 1), data: "11"},
|
||||
{loc: "root", path: monthVal(greMon, "format", "narrow", 2), data: "2"},
|
||||
{loc: "root", path: monthVal(greMon, "stand-alone", "wide", 3), data: "33"},
|
||||
{loc: "root", path: monthVal(greMon, "stand-alone", "narrow", 4), data: "4"},
|
||||
{loc: "root", path: monthVal(budMon, "format", "wide", 1), data: "11"},
|
||||
{loc: "root", path: monthVal(budMon, "format", "narrow", 2), data: "2"},
|
||||
{loc: "root", path: monthVal(budMon, "stand-alone", "wide", 3), data: "33"},
|
||||
{loc: "root", path: monthVal(budMon, "stand-alone", "narrow", 4), data: "4"},
|
||||
}
|
||||
|
||||
// 19
|
||||
var deGetTests = []getTest{
|
||||
{loc: "de", path: "identity/language", typ: "de"},
|
||||
{loc: "de", path: "posix", length: 2},
|
||||
{loc: "de", path: "characters", field: "exemplarCharacters", length: 4},
|
||||
{loc: "de", path: "characters/exemplarCharacters[@type='auxiliary']", data: `[á à ă]`},
|
||||
// identity is a blocking element, so de should not inherit generation from root.
|
||||
{loc: "de", path: "identity/generation", missing: true},
|
||||
// default resolution
|
||||
{loc: "root", path: "dates/calendars/calendar", typ: "gregorian"},
|
||||
|
||||
// absolute path alias resolution
|
||||
{loc: "gsw", path: "posix", field: "messages", length: 1},
|
||||
{loc: "gsw", path: "posix/messages/yesstr", data: "yes:y"},
|
||||
}
|
||||
|
||||
// 27(greMon) - 52(budMon) - 77(chnMon)
|
||||
func calGetTests(s string) []getTest {
|
||||
tests := []getTest{
|
||||
{loc: "de", path: s, length: 2},
|
||||
{loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='wide']", field: "month", length: 5},
|
||||
{loc: "de", path: monthVal(s, "format", "wide", 1), data: "11"},
|
||||
{loc: "de", path: monthVal(s, "format", "wide", 2), data: "22"},
|
||||
{loc: "de", path: monthVal(s, "format", "wide", 3), data: "Maerz", altData: "bbb"},
|
||||
{loc: "de", path: monthVal(s, "format", "wide", 4), data: "April"},
|
||||
{loc: "de", path: monthVal(s, "format", "wide", 5), data: "Mai"},
|
||||
|
||||
{loc: "de", path: s + "monthContext[@type='format']/monthWidth[@type='narrow']", field: "month", length: 5},
|
||||
{loc: "de", path: monthVal(s, "format", "narrow", 1), data: "1"},
|
||||
{loc: "de", path: monthVal(s, "format", "narrow", 2), data: "2"},
|
||||
{loc: "de", path: monthVal(s, "format", "narrow", 3), data: "M", altData: "BBB"},
|
||||
{loc: "de", path: monthVal(s, "format", "narrow", 4), data: "A"},
|
||||
{loc: "de", path: monthVal(s, "format", "narrow", 5), data: "m"},
|
||||
|
||||
{loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='wide']", field: "month", length: 5},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "wide", 1), data: "11"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "wide", 2), data: "22"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "wide", 3), data: "Maerz", altData: "bbb"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "wide", 4), data: "april"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "wide", 5), data: "mai"},
|
||||
|
||||
{loc: "de", path: s + "monthContext[@type='stand-alone']/monthWidth[@type='narrow']", field: "month", length: 5},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "narrow", 1), data: "1"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "narrow", 2), data: "2"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "narrow", 3), data: "m"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "narrow", 4), data: "4"},
|
||||
{loc: "de", path: monthVal(s, "stand-alone", "narrow", 5), data: "m"},
|
||||
}
|
||||
if s == budMon {
|
||||
for i, t := range tests {
|
||||
if t.altData != "" {
|
||||
tests[i].data = t.altData
|
||||
}
|
||||
}
|
||||
}
|
||||
return tests
|
||||
}
|
||||
|
||||
var getTests = append(rootGetTests,
|
||||
append(deGetTests,
|
||||
append(calGetTests(greMon),
|
||||
append(calGetTests(budMon),
|
||||
calGetTests(chnMon)...)...)...)...)
|
||||
|
||||
func TestPath(t *testing.T) {
|
||||
d := data()
|
||||
for i, tt := range getTests {
|
||||
x, _ := d.LDML(tt.loc)
|
||||
e, err := walkXPath(x, tt.path)
|
||||
if err != nil {
|
||||
if !tt.missing {
|
||||
t.Errorf("%d:error: %v %v", i, err, tt.missing)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if tt.missing {
|
||||
t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing)
|
||||
continue
|
||||
}
|
||||
if tt.data != "" && e.GetCommon().Data() != tt.data {
|
||||
t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data)
|
||||
continue
|
||||
}
|
||||
if tt.typ != "" && e.GetCommon().Type != tt.typ {
|
||||
t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ)
|
||||
continue
|
||||
}
|
||||
if tt.field != "" {
|
||||
slice, _ := findField(reflect.ValueOf(e), tt.field)
|
||||
if slice.Len() != tt.length {
|
||||
t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
d := data()
|
||||
for i, tt := range getTests {
|
||||
x, _ := d.LDML(tt.loc)
|
||||
e, err := Get(x, tt.path)
|
||||
if err != nil {
|
||||
if !tt.missing {
|
||||
t.Errorf("%d:error: %v %v", i, err, tt.missing)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if tt.missing {
|
||||
t.Errorf("%d: missing is %v; want %v", i, e == nil, tt.missing)
|
||||
continue
|
||||
}
|
||||
if tt.data != "" && e.GetCommon().Data() != tt.data {
|
||||
t.Errorf("%d: data is %v; want %v", i, e.GetCommon().Data(), tt.data)
|
||||
continue
|
||||
}
|
||||
if tt.typ != "" && e.GetCommon().Type != tt.typ {
|
||||
t.Errorf("%d: type is %v; want %v", i, e.GetCommon().Type, tt.typ)
|
||||
continue
|
||||
}
|
||||
if tt.field != "" {
|
||||
slice, _ := findField(reflect.ValueOf(e), tt.field)
|
||||
if slice.Len() != tt.length {
|
||||
t.Errorf("%d: length is %v; want %v", i, slice.Len(), tt.length)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
144
vendor/golang.org/x/text/unicode/cldr/slice.go
generated
vendored
Normal file
144
vendor/golang.org/x/text/unicode/cldr/slice.go
generated
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Slice provides utilities for modifying slices of elements.
|
||||
// It can be wrapped around any slice of which the element type implements
|
||||
// interface Elem.
|
||||
type Slice struct {
|
||||
ptr reflect.Value
|
||||
typ reflect.Type
|
||||
}
|
||||
|
||||
// Value returns the reflect.Value of the underlying slice.
|
||||
func (s *Slice) Value() reflect.Value {
|
||||
return s.ptr.Elem()
|
||||
}
|
||||
|
||||
// MakeSlice wraps a pointer to a slice of Elems.
|
||||
// It replaces the array pointed to by the slice so that subsequent modifications
|
||||
// do not alter the data in a CLDR type.
|
||||
// It panics if an incorrect type is passed.
|
||||
func MakeSlice(slicePtr interface{}) Slice {
|
||||
ptr := reflect.ValueOf(slicePtr)
|
||||
if ptr.Kind() != reflect.Ptr {
|
||||
panic(fmt.Sprintf("MakeSlice: argument must be pointer to slice, found %v", ptr.Type()))
|
||||
}
|
||||
sl := ptr.Elem()
|
||||
if sl.Kind() != reflect.Slice {
|
||||
panic(fmt.Sprintf("MakeSlice: argument must point to a slice, found %v", sl.Type()))
|
||||
}
|
||||
intf := reflect.TypeOf((*Elem)(nil)).Elem()
|
||||
if !sl.Type().Elem().Implements(intf) {
|
||||
panic(fmt.Sprintf("MakeSlice: element type of slice (%v) does not implement Elem", sl.Type().Elem()))
|
||||
}
|
||||
nsl := reflect.MakeSlice(sl.Type(), sl.Len(), sl.Len())
|
||||
reflect.Copy(nsl, sl)
|
||||
sl.Set(nsl)
|
||||
return Slice{
|
||||
ptr: ptr,
|
||||
typ: sl.Type().Elem().Elem(),
|
||||
}
|
||||
}
|
||||
|
||||
func (s Slice) indexForAttr(a string) []int {
|
||||
for i := iter(reflect.Zero(s.typ)); !i.done(); i.next() {
|
||||
if n, _ := xmlName(i.field()); n == a {
|
||||
return i.index
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("MakeSlice: no attribute %q for type %v", a, s.typ))
|
||||
}
|
||||
|
||||
// Filter filters s to only include elements for which fn returns true.
|
||||
func (s Slice) Filter(fn func(e Elem) bool) {
|
||||
k := 0
|
||||
sl := s.Value()
|
||||
for i := 0; i < sl.Len(); i++ {
|
||||
vi := sl.Index(i)
|
||||
if fn(vi.Interface().(Elem)) {
|
||||
sl.Index(k).Set(vi)
|
||||
k++
|
||||
}
|
||||
}
|
||||
sl.Set(sl.Slice(0, k))
|
||||
}
|
||||
|
||||
// Group finds elements in s for which fn returns the same value and groups
|
||||
// them in a new Slice.
|
||||
func (s Slice) Group(fn func(e Elem) string) []Slice {
|
||||
m := make(map[string][]reflect.Value)
|
||||
sl := s.Value()
|
||||
for i := 0; i < sl.Len(); i++ {
|
||||
vi := sl.Index(i)
|
||||
key := fn(vi.Interface().(Elem))
|
||||
m[key] = append(m[key], vi)
|
||||
}
|
||||
keys := []string{}
|
||||
for k, _ := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
res := []Slice{}
|
||||
for _, k := range keys {
|
||||
nsl := reflect.New(sl.Type())
|
||||
nsl.Elem().Set(reflect.Append(nsl.Elem(), m[k]...))
|
||||
res = append(res, MakeSlice(nsl.Interface()))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// SelectAnyOf filters s to contain only elements for which attr matches
|
||||
// any of the values.
|
||||
func (s Slice) SelectAnyOf(attr string, values ...string) {
|
||||
index := s.indexForAttr(attr)
|
||||
s.Filter(func(e Elem) bool {
|
||||
vf := reflect.ValueOf(e).Elem().FieldByIndex(index)
|
||||
return in(values, vf.String())
|
||||
})
|
||||
}
|
||||
|
||||
// SelectOnePerGroup filters s to include at most one element e per group of
|
||||
// elements matching Key(attr), where e has an attribute a that matches any
|
||||
// the values in v.
|
||||
// If more than one element in a group matches a value in v preference
|
||||
// is given to the element that matches the first value in v.
|
||||
func (s Slice) SelectOnePerGroup(a string, v []string) {
|
||||
index := s.indexForAttr(a)
|
||||
grouped := s.Group(func(e Elem) string { return Key(e, a) })
|
||||
sl := s.Value()
|
||||
sl.Set(sl.Slice(0, 0))
|
||||
for _, g := range grouped {
|
||||
e := reflect.Value{}
|
||||
found := len(v)
|
||||
gsl := g.Value()
|
||||
for i := 0; i < gsl.Len(); i++ {
|
||||
vi := gsl.Index(i).Elem().FieldByIndex(index)
|
||||
j := 0
|
||||
for ; j < len(v) && v[j] != vi.String(); j++ {
|
||||
}
|
||||
if j < found {
|
||||
found = j
|
||||
e = gsl.Index(i)
|
||||
}
|
||||
}
|
||||
if found < len(v) {
|
||||
sl.Set(reflect.Append(sl, e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SelectDraft drops all elements from the list with a draft level smaller than d
|
||||
// and selects the highest draft level of the remaining.
|
||||
// This method assumes that the input CLDR is canonicalized.
|
||||
func (s Slice) SelectDraft(d Draft) {
|
||||
s.SelectOnePerGroup("draft", drafts[len(drafts)-2-int(d):])
|
||||
}
|
175
vendor/golang.org/x/text/unicode/cldr/slice_test.go
generated
vendored
Normal file
175
vendor/golang.org/x/text/unicode/cldr/slice_test.go
generated
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type testSlice []*Common
|
||||
|
||||
func mkElem(alt, typ, ref string) *Common {
|
||||
return &Common{
|
||||
Type: typ,
|
||||
Reference: ref,
|
||||
Alt: alt,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
testSlice1 = testSlice{
|
||||
mkElem("1", "a", "i.a"),
|
||||
mkElem("1", "b", "i.b"),
|
||||
mkElem("1", "c", "i.c"),
|
||||
mkElem("2", "b", "ii"),
|
||||
mkElem("3", "c", "iii"),
|
||||
mkElem("4", "a", "iv.a"),
|
||||
mkElem("4", "d", "iv.d"),
|
||||
}
|
||||
testSliceE = testSlice{}
|
||||
)
|
||||
|
||||
func panics(f func()) (panics bool) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
panics = true
|
||||
}
|
||||
}()
|
||||
f()
|
||||
return panics
|
||||
}
|
||||
|
||||
func TestMakeSlice(t *testing.T) {
|
||||
foo := 1
|
||||
bar := []int{}
|
||||
tests := []struct {
|
||||
i interface{}
|
||||
panics bool
|
||||
err string
|
||||
}{
|
||||
{&foo, true, "should panic when passed a pointer to the wrong type"},
|
||||
{&bar, true, "should panic when slice element of the wrong type"},
|
||||
{testSlice1, true, "should panic when passed a slice"},
|
||||
{&testSlice1, false, "should not panic"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
if panics(func() { MakeSlice(tt.i) }) != tt.panics {
|
||||
t.Errorf("%d: %s", i, tt.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var anyOfTests = []struct {
|
||||
sl testSlice
|
||||
values []string
|
||||
n int
|
||||
}{
|
||||
{testSliceE, []string{}, 0},
|
||||
{testSliceE, []string{"1", "2", "3"}, 0},
|
||||
{testSlice1, []string{}, 0},
|
||||
{testSlice1, []string{"1"}, 3},
|
||||
{testSlice1, []string{"2"}, 1},
|
||||
{testSlice1, []string{"5"}, 0},
|
||||
{testSlice1, []string{"1", "2", "3"}, 5},
|
||||
}
|
||||
|
||||
func TestSelectAnyOf(t *testing.T) {
|
||||
for i, tt := range anyOfTests {
|
||||
sl := tt.sl
|
||||
s := MakeSlice(&sl)
|
||||
s.SelectAnyOf("alt", tt.values...)
|
||||
if len(sl) != tt.n {
|
||||
t.Errorf("%d: found len == %d; want %d", i, len(sl), tt.n)
|
||||
}
|
||||
}
|
||||
sl := testSlice1
|
||||
s := MakeSlice(&sl)
|
||||
if !panics(func() { s.SelectAnyOf("foo") }) {
|
||||
t.Errorf("should panic on non-existing attribute")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
for i, tt := range anyOfTests {
|
||||
sl := tt.sl
|
||||
s := MakeSlice(&sl)
|
||||
s.Filter(func(e Elem) bool {
|
||||
v, _ := findField(reflect.ValueOf(e), "alt")
|
||||
return in(tt.values, v.String())
|
||||
})
|
||||
if len(sl) != tt.n {
|
||||
t.Errorf("%d: found len == %d; want %d", i, len(sl), tt.n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroup(t *testing.T) {
|
||||
f := func(excl ...string) func(Elem) string {
|
||||
return func(e Elem) string {
|
||||
return Key(e, excl...)
|
||||
}
|
||||
}
|
||||
tests := []struct {
|
||||
sl testSlice
|
||||
f func(Elem) string
|
||||
lens []int
|
||||
}{
|
||||
{testSliceE, f(), []int{}},
|
||||
{testSlice1, f(), []int{1, 1, 1, 1, 1, 1, 1}},
|
||||
{testSlice1, f("type"), []int{3, 1, 1, 2}},
|
||||
{testSlice1, f("alt"), []int{2, 2, 2, 1}},
|
||||
{testSlice1, f("alt", "type"), []int{7}},
|
||||
{testSlice1, f("alt", "type"), []int{7}},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
sl := tt.sl
|
||||
s := MakeSlice(&sl)
|
||||
g := s.Group(tt.f)
|
||||
if len(tt.lens) != len(g) {
|
||||
t.Errorf("%d: found %d; want %d", i, len(g), len(tt.lens))
|
||||
continue
|
||||
}
|
||||
for j, v := range tt.lens {
|
||||
if n := g[j].Value().Len(); n != v {
|
||||
t.Errorf("%d: found %d for length of group %d; want %d", i, n, j, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectOnePerGroup(t *testing.T) {
|
||||
tests := []struct {
|
||||
sl testSlice
|
||||
attr string
|
||||
values []string
|
||||
refs []string
|
||||
}{
|
||||
{testSliceE, "alt", []string{"1"}, []string{}},
|
||||
{testSliceE, "type", []string{"a"}, []string{}},
|
||||
{testSlice1, "alt", []string{"2", "3", "1"}, []string{"i.a", "ii", "iii"}},
|
||||
{testSlice1, "alt", []string{"1", "4"}, []string{"i.a", "i.b", "i.c", "iv.d"}},
|
||||
{testSlice1, "type", []string{"c", "d"}, []string{"i.c", "iii", "iv.d"}},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
sl := tt.sl
|
||||
s := MakeSlice(&sl)
|
||||
s.SelectOnePerGroup(tt.attr, tt.values)
|
||||
if len(sl) != len(tt.refs) {
|
||||
t.Errorf("%d: found result length %d; want %d", i, len(sl), len(tt.refs))
|
||||
continue
|
||||
}
|
||||
for j, e := range sl {
|
||||
if tt.refs[j] != e.Reference {
|
||||
t.Errorf("%d:%d found %s; want %s", i, j, e.Reference, tt.refs[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
sl := testSlice1
|
||||
s := MakeSlice(&sl)
|
||||
if !panics(func() { s.SelectOnePerGroup("foo", nil) }) {
|
||||
t.Errorf("should panic on non-existing attribute")
|
||||
}
|
||||
}
|
1494
vendor/golang.org/x/text/unicode/cldr/xml.go
generated
vendored
Normal file
1494
vendor/golang.org/x/text/unicode/cldr/xml.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue