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.
12 // A Builder allows constructing a Tag from individual components.
13 // Its main user is Compose in the top-level language package.
17 private string // the x extension
22 // Make returns a new Tag from the current settings.
23 func (b *Builder) Make() Tag {
26 if len(b.extensions) > 0 || len(b.variants) > 0 {
27 sort.Sort(sortVariants(b.variants))
28 sort.Strings(b.extensions)
31 b.extensions = append(b.extensions, b.private)
33 n := maxCoreSize + tokenLen(b.variants...) + tokenLen(b.extensions...)
34 buf := make([]byte, n)
35 p := t.genCoreBytes(buf)
37 p += appendTokens(buf[p:], b.variants...)
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, "")
47 } else if b.private != "" {
54 // SetTag copies all the settings from a given Tag. Any previously set values
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
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)
67 b.extensions, b.private = b.extensions[:0], ""
68 for _, e := range t.Extensions() {
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) {
83 for i, s := range b.extensions {
86 b.extensions[i] += e[1:]
91 b.extensions = append(b.extensions, e)
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
98 func (b *Builder) SetExt(e string) {
103 for i, s := range b.extensions {
106 b.extensions[i] = e + s[1:]
113 b.extensions = append(b.extensions, e)
116 // AddVariant adds any number of variants.
117 func (b *Builder) AddVariant(v ...string) {
118 for _, v := range v {
120 b.variants = append(b.variants, v)
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]
131 // ClearExtensions removes any extensions previously added, including those
132 // copied from a Tag in SetTag.
133 func (b *Builder) ClearExtensions() {
135 b.extensions = b.extensions[:0]
138 func tokenLen(token ...string) (n int) {
139 for _, t := range token {
145 func appendTokens(b []byte, token ...string) int {
147 for _, t := range token {
155 type sortVariants []string
157 func (s sortVariants) Len() int {
161 func (s sortVariants) Swap(i, j int) {
162 s[j], s[i] = s[i], s[j]
165 func (s sortVariants) Less(i, j int) bool {
166 return variantIndex[s[i]] < variantIndex[s[j]]