1
2
3
4
5 package language
6
7 import (
8 "sort"
9 "strings"
10 )
11
12
13
14 type Builder struct {
15 Tag Tag
16
17 private string
18 variants []string
19 extensions []string
20 }
21
22
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
42
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
55
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
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
74
75
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
95
96
97
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
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
126
127 func (b *Builder) ClearVariants() {
128 b.variants = b.variants[:0]
129 }
130
131
132
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 }
168
View as plain text