...
1
2
3
4
5 package collate
6
7 import (
8 "sort"
9
10 "golang.org/x/text/internal/colltab"
11 "golang.org/x/text/language"
12 "golang.org/x/text/unicode/norm"
13 )
14
15
16 func newCollator(t colltab.Weighter) *Collator {
17
18 c := &Collator{
19 options: options{
20 ignore: [colltab.NumLevels]bool{
21 colltab.Quaternary: true,
22 colltab.Identity: true,
23 },
24 f: norm.NFD,
25 t: t,
26 },
27 }
28
29
30 c.variableTop = t.Top()
31
32 return c
33 }
34
35
36
37 type Option struct {
38 priority int
39 f func(o *options)
40 }
41
42 type prioritizedOptions []Option
43
44 func (p prioritizedOptions) Len() int {
45 return len(p)
46 }
47
48 func (p prioritizedOptions) Swap(i, j int) {
49 p[i], p[j] = p[j], p[i]
50 }
51
52 func (p prioritizedOptions) Less(i, j int) bool {
53 return p[i].priority < p[j].priority
54 }
55
56 type options struct {
57
58 ignore [colltab.NumLevels]bool
59
60
61
62 caseLevel bool
63
64
65
66 backwards bool
67
68
69
70
71
72 numeric bool
73
74
75 alternate alternateHandling
76
77
78
79 variableTop uint32
80
81 t colltab.Weighter
82
83 f norm.Form
84 }
85
86 func (o *options) setOptions(opts []Option) {
87 sort.Sort(prioritizedOptions(opts))
88 for _, x := range opts {
89 x.f(o)
90 }
91 }
92
93
94
95
96 func OptionsFromTag(t language.Tag) Option {
97 return Option{0, func(o *options) {
98 o.setFromTag(t)
99 }}
100 }
101
102 func (o *options) setFromTag(t language.Tag) {
103 o.caseLevel = ldmlBool(t, o.caseLevel, "kc")
104 o.backwards = ldmlBool(t, o.backwards, "kb")
105 o.numeric = ldmlBool(t, o.numeric, "kn")
106
107
108 switch t.TypeForKey("ks") {
109 case "level1":
110 o.ignore[colltab.Secondary] = true
111 o.ignore[colltab.Tertiary] = true
112 case "level2":
113 o.ignore[colltab.Tertiary] = true
114 case "level3", "":
115
116 case "level4":
117 o.ignore[colltab.Quaternary] = false
118 case "identic":
119 o.ignore[colltab.Quaternary] = false
120 o.ignore[colltab.Identity] = false
121 }
122
123 switch t.TypeForKey("ka") {
124 case "shifted":
125 o.alternate = altShifted
126
127
128
129
130 case "blanked":
131 o.alternate = altBlanked
132 case "posix":
133 o.alternate = altShiftTrimmed
134 }
135
136
137
138
139
140
141 }
142
143 func ldmlBool(t language.Tag, old bool, key string) bool {
144 switch t.TypeForKey(key) {
145 case "true":
146 return true
147 case "false":
148 return false
149 default:
150 return old
151 }
152 }
153
154 var (
155
156 IgnoreCase Option = ignoreCase
157 ignoreCase = Option{3, ignoreCaseF}
158
159
160 IgnoreDiacritics Option = ignoreDiacritics
161 ignoreDiacritics = Option{3, ignoreDiacriticsF}
162
163
164
165 IgnoreWidth Option = ignoreWidth
166 ignoreWidth = Option{2, ignoreWidthF}
167
168
169 Loose Option = loose
170 loose = Option{4, looseF}
171
172
173 Force Option = force
174 force = Option{5, forceF}
175
176
177 Numeric Option = numeric
178 numeric = Option{5, numericF}
179 )
180
181 func ignoreWidthF(o *options) {
182 o.ignore[colltab.Tertiary] = true
183 o.caseLevel = true
184 }
185
186 func ignoreDiacriticsF(o *options) {
187 o.ignore[colltab.Secondary] = true
188 }
189
190 func ignoreCaseF(o *options) {
191 o.ignore[colltab.Tertiary] = true
192 o.caseLevel = false
193 }
194
195 func looseF(o *options) {
196 ignoreWidthF(o)
197 ignoreDiacriticsF(o)
198 ignoreCaseF(o)
199 }
200
201 func forceF(o *options) {
202 o.ignore[colltab.Identity] = false
203 }
204
205 func numericF(o *options) { o.numeric = true }
206
207
208 func Reorder(s ...string) Option {
209
210 panic("TODO: implement")
211 }
212
213
214
215
216
217
218
219
220
221 type alternateHandling int
222
223 const (
224
225 altNonIgnorable alternateHandling = iota
226
227
228
229
230 altBlanked
231
232
233
234 altShifted
235
236
237
238 altShiftTrimmed
239 )
240
View as plain text