barometer: update DMA's vendoring packages
[barometer.git] / src / dma / vendor / golang.org / x / text / internal / language / compose.go
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package language
6
7 import (
8         "sort"
9         "strings"
10 )
11
12 // A Builder allows constructing a Tag from individual components.
13 // Its main user is Compose in the top-level language package.
14 type Builder struct {
15         Tag Tag
16
17         private    string // the x extension
18         variants   []string
19         extensions []string
20 }
21
22 // Make returns a new Tag from the current settings.
23 func (b *Builder) Make() Tag {
24         t := b.Tag
25
26         if len(b.extensions) > 0 || len(b.variants) > 0 {
27                 sort.Sort(sortVariants(b.variants))
28                 sort.Strings(b.extensions)
29
30                 if b.private != "" {
31                         b.extensions = append(b.extensions, b.private)
32                 }
33                 n := maxCoreSize + tokenLen(b.variants...) + tokenLen(b.extensions...)
34                 buf := make([]byte, n)
35                 p := t.genCoreBytes(buf)
36                 t.pVariant = byte(p)
37                 p += appendTokens(buf[p:], b.variants...)
38                 t.pExt = uint16(p)
39                 p += appendTokens(buf[p:], b.extensions...)
40                 t.str = string(buf[:p])
41                 // We may not always need to remake the string, but when or when not
42                 // to do so is rather tricky.
43                 scan := makeScanner(buf[:p])
44                 t, _ = parse(&scan, "")
45                 return t
46
47         } else if b.private != "" {
48                 t.str = b.private
49                 t.RemakeString()
50         }
51         return t
52 }
53
54 // SetTag copies all the settings from a given Tag. Any previously set values
55 // are discarded.
56 func (b *Builder) SetTag(t Tag) {
57         b.Tag.LangID = t.LangID
58         b.Tag.RegionID = t.RegionID
59         b.Tag.ScriptID = t.ScriptID
60         // TODO: optimize
61         b.variants = b.variants[:0]
62         if variants := t.Variants(); variants != "" {
63                 for _, vr := range strings.Split(variants[1:], "-") {
64                         b.variants = append(b.variants, vr)
65                 }
66         }
67         b.extensions, b.private = b.extensions[:0], ""
68         for _, e := range t.Extensions() {
69                 b.AddExt(e)
70         }
71 }
72
73 // AddExt adds extension e to the tag. e must be a valid extension as returned
74 // by Tag.Extension. If the extension already exists, it will be discarded,
75 // except for a -u extension, where non-existing key-type pairs will added.
76 func (b *Builder) AddExt(e string) {
77         if e[0] == 'x' {
78                 if b.private == "" {
79                         b.private = e
80                 }
81                 return
82         }
83         for i, s := range b.extensions {
84                 if s[0] == e[0] {
85                         if e[0] == 'u' {
86                                 b.extensions[i] += e[1:]
87                         }
88                         return
89                 }
90         }
91         b.extensions = append(b.extensions, e)
92 }
93
94 // SetExt sets the extension e to the tag. e must be a valid extension as
95 // returned by Tag.Extension. If the extension already exists, it will be
96 // overwritten, except for a -u extension, where the individual key-type pairs
97 // will be set.
98 func (b *Builder) SetExt(e string) {
99         if e[0] == 'x' {
100                 b.private = e
101                 return
102         }
103         for i, s := range b.extensions {
104                 if s[0] == e[0] {
105                         if e[0] == 'u' {
106                                 b.extensions[i] = e + s[1:]
107                         } else {
108                                 b.extensions[i] = e
109                         }
110                         return
111                 }
112         }
113         b.extensions = append(b.extensions, e)
114 }
115
116 // AddVariant adds any number of variants.
117 func (b *Builder) AddVariant(v ...string) {
118         for _, v := range v {
119                 if v != "" {
120                         b.variants = append(b.variants, v)
121                 }
122         }
123 }
124
125 // ClearVariants removes any variants previously added, including those
126 // copied from a Tag in SetTag.
127 func (b *Builder) ClearVariants() {
128         b.variants = b.variants[:0]
129 }
130
131 // ClearExtensions removes any extensions previously added, including those
132 // copied from a Tag in SetTag.
133 func (b *Builder) ClearExtensions() {
134         b.private = ""
135         b.extensions = b.extensions[:0]
136 }
137
138 func tokenLen(token ...string) (n int) {
139         for _, t := range token {
140                 n += len(t) + 1
141         }
142         return
143 }
144
145 func appendTokens(b []byte, token ...string) int {
146         p := 0
147         for _, t := range token {
148                 b[p] = '-'
149                 copy(b[p+1:], t)
150                 p += 1 + len(t)
151         }
152         return p
153 }
154
155 type sortVariants []string
156
157 func (s sortVariants) Len() int {
158         return len(s)
159 }
160
161 func (s sortVariants) Swap(i, j int) {
162         s[j], s[i] = s[i], s[j]
163 }
164
165 func (s sortVariants) Less(i, j int) bool {
166         return variantIndex[s[i]] < variantIndex[s[j]]
167 }