summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/internal/cldrtree/tree.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/internal/cldrtree/tree.go')
-rw-r--r--vendor/golang.org/x/text/internal/cldrtree/tree.go181
1 files changed, 181 insertions, 0 deletions
diff --git a/vendor/golang.org/x/text/internal/cldrtree/tree.go b/vendor/golang.org/x/text/internal/cldrtree/tree.go
new file mode 100644
index 0000000..6d4084b
--- /dev/null
+++ b/vendor/golang.org/x/text/internal/cldrtree/tree.go
@@ -0,0 +1,181 @@
+// Copyright 2017 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 cldrtree
+
+import (
+ "golang.org/x/text/internal"
+ "golang.org/x/text/language"
+)
+
+const (
+ inheritOffsetShift = 12
+ inheritMask uint16 = 0x8000
+ inheritValueMask uint16 = 0x0FFF
+
+ missingValue uint16 = 0xFFFF
+)
+
+// Tree holds a tree of CLDR data.
+type Tree struct {
+ Locales []uint32
+ Indices []uint16
+ Buckets []string
+}
+
+// Lookup looks up CLDR data for the given path. The lookup adheres to the alias
+// and locale inheritance rules as defined in CLDR.
+//
+// Each subsequent element in path indicates which subtree to select data from.
+// The last element of the path must select a leaf node. All other elements
+// of the path select a subindex.
+func (t *Tree) Lookup(tag int, path ...uint16) string {
+ return t.lookup(tag, false, path...)
+}
+
+// LookupFeature is like Lookup, but will first check whether a value of "other"
+// as a fallback before traversing the inheritance chain.
+func (t *Tree) LookupFeature(tag int, path ...uint16) string {
+ return t.lookup(tag, true, path...)
+}
+
+func (t *Tree) lookup(tag int, isFeature bool, path ...uint16) string {
+ origLang := tag
+outer:
+ for {
+ index := t.Indices[t.Locales[tag]:]
+
+ k := uint16(0)
+ for i := range path {
+ max := index[k]
+ if i < len(path)-1 {
+ // index (non-leaf)
+ if path[i] >= max {
+ break
+ }
+ k = index[k+1+path[i]]
+ if k == 0 {
+ break
+ }
+ if v := k &^ inheritMask; k != v {
+ offset := v >> inheritOffsetShift
+ value := v & inheritValueMask
+ path[uint16(i)-offset] = value
+ tag = origLang
+ continue outer
+ }
+ } else {
+ // leaf value
+ offset := missingValue
+ if path[i] < max {
+ offset = index[k+2+path[i]]
+ }
+ if offset == missingValue {
+ if !isFeature {
+ break
+ }
+ // "other" feature must exist
+ offset = index[k+2]
+ }
+ data := t.Buckets[index[k+1]]
+ n := uint16(data[offset])
+ return data[offset+1 : offset+n+1]
+ }
+ }
+ if tag == 0 {
+ break
+ }
+ tag = int(internal.Parent[tag])
+ }
+ return ""
+}
+
+func build(b *Builder) (*Tree, error) {
+ var t Tree
+
+ t.Locales = make([]uint32, language.NumCompactTags)
+
+ for _, loc := range b.locales {
+ tag, _ := language.CompactIndex(loc.tag)
+ t.Locales[tag] = uint32(len(t.Indices))
+ var x indexBuilder
+ x.add(loc.root)
+ t.Indices = append(t.Indices, x.index...)
+ }
+ // Set locales for which we don't have data to the parent's data.
+ for i, v := range t.Locales {
+ p := uint16(i)
+ for v == 0 && p != 0 {
+ p = internal.Parent[p]
+ v = t.Locales[p]
+ }
+ t.Locales[i] = v
+ }
+
+ for _, b := range b.buckets {
+ t.Buckets = append(t.Buckets, string(b))
+ }
+ if b.err != nil {
+ return nil, b.err
+ }
+ return &t, nil
+}
+
+type indexBuilder struct {
+ index []uint16
+}
+
+func (b *indexBuilder) add(i *Index) uint16 {
+ offset := len(b.index)
+
+ max := enumIndex(0)
+ switch {
+ case len(i.values) > 0:
+ for _, v := range i.values {
+ if v.key > max {
+ max = v.key
+ }
+ }
+ b.index = append(b.index, make([]uint16, max+3)...)
+
+ b.index[offset] = uint16(max) + 1
+
+ b.index[offset+1] = i.values[0].value.bucket
+ for i := offset + 2; i < len(b.index); i++ {
+ b.index[i] = missingValue
+ }
+ for _, v := range i.values {
+ b.index[offset+2+int(v.key)] = v.value.bucketPos
+ }
+ return uint16(offset)
+
+ case len(i.subIndex) > 0:
+ for _, s := range i.subIndex {
+ if s.meta.index > max {
+ max = s.meta.index
+ }
+ }
+ b.index = append(b.index, make([]uint16, max+2)...)
+
+ b.index[offset] = uint16(max) + 1
+
+ for _, s := range i.subIndex {
+ x := b.add(s)
+ b.index[offset+int(s.meta.index)+1] = x
+ }
+ return uint16(offset)
+
+ case i.meta.inheritOffset < 0:
+ v := uint16(-(i.meta.inheritOffset + 1)) << inheritOffsetShift
+ p := i.meta
+ for k := i.meta.inheritOffset; k < 0; k++ {
+ p = p.parent
+ }
+ v += uint16(p.typeInfo.enum.lookup(i.meta.inheritIndex))
+ v |= inheritMask
+ return v
+ }
+
+ return 0
+}