...
Source file src/pkg/vendor/golang.org/x/text/unicode/norm/forminfo.go
1
2
3
4
5 package norm
6
7 import "encoding/binary"
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 const (
34 qcInfoMask = 0x3F
35 headerLenMask = 0x3F
36 headerFlagsMask = 0xC0
37 )
38
39
40 type Properties struct {
41 pos uint8
42 size uint8
43 ccc uint8
44 tccc uint8
45 nLead uint8
46 flags qcInfo
47 index uint16
48 }
49
50
51 type lookupFunc func(b input, i int) Properties
52
53
54 type formInfo struct {
55 form Form
56 composing, compatibility bool
57 info lookupFunc
58 nextMain iterFunc
59 }
60
61 var formTable = []*formInfo{{
62 form: NFC,
63 composing: true,
64 compatibility: false,
65 info: lookupInfoNFC,
66 nextMain: nextComposed,
67 }, {
68 form: NFD,
69 composing: false,
70 compatibility: false,
71 info: lookupInfoNFC,
72 nextMain: nextDecomposed,
73 }, {
74 form: NFKC,
75 composing: true,
76 compatibility: true,
77 info: lookupInfoNFKC,
78 nextMain: nextComposed,
79 }, {
80 form: NFKD,
81 composing: false,
82 compatibility: true,
83 info: lookupInfoNFKC,
84 nextMain: nextDecomposed,
85 }}
86
87
88
89
90
91
92
93
94
95 func (p Properties) BoundaryBefore() bool {
96 if p.ccc == 0 && !p.combinesBackward() {
97 return true
98 }
99
100
101
102 return false
103 }
104
105
106
107 func (p Properties) BoundaryAfter() bool {
108
109 return p.isInert()
110 }
111
112
113
114
115
116
117
118
119
120 type qcInfo uint8
121
122 func (p Properties) isYesC() bool { return p.flags&0x10 == 0 }
123 func (p Properties) isYesD() bool { return p.flags&0x4 == 0 }
124
125 func (p Properties) combinesForward() bool { return p.flags&0x20 != 0 }
126 func (p Properties) combinesBackward() bool { return p.flags&0x8 != 0 }
127 func (p Properties) hasDecomposition() bool { return p.flags&0x4 != 0 }
128
129 func (p Properties) isInert() bool {
130 return p.flags&qcInfoMask == 0 && p.ccc == 0
131 }
132
133 func (p Properties) multiSegment() bool {
134 return p.index >= firstMulti && p.index < endMulti
135 }
136
137 func (p Properties) nLeadingNonStarters() uint8 {
138 return p.nLead
139 }
140
141 func (p Properties) nTrailingNonStarters() uint8 {
142 return uint8(p.flags & 0x03)
143 }
144
145
146
147 func (p Properties) Decomposition() []byte {
148
149 if p.index == 0 {
150 return nil
151 }
152 i := p.index
153 n := decomps[i] & headerLenMask
154 i++
155 return decomps[i : i+uint16(n)]
156 }
157
158
159 func (p Properties) Size() int {
160 return int(p.size)
161 }
162
163
164 func (p Properties) CCC() uint8 {
165 if p.index >= firstCCCZeroExcept {
166 return 0
167 }
168 return ccc[p.ccc]
169 }
170
171
172
173 func (p Properties) LeadCCC() uint8 {
174 return ccc[p.ccc]
175 }
176
177
178
179 func (p Properties) TrailCCC() uint8 {
180 return ccc[p.tccc]
181 }
182
183 func buildRecompMap() {
184 recompMap = make(map[uint32]rune, len(recompMapPacked)/8)
185 var buf [8]byte
186 for i := 0; i < len(recompMapPacked); i += 8 {
187 copy(buf[:], recompMapPacked[i:i+8])
188 key := binary.BigEndian.Uint32(buf[:4])
189 val := binary.BigEndian.Uint32(buf[4:])
190 recompMap[key] = rune(val)
191 }
192 }
193
194
195
196
197
198
199
200
201
202
203
204
205 func combine(a, b rune) rune {
206 key := uint32(uint16(a))<<16 + uint32(uint16(b))
207 if recompMap == nil {
208 panic("caller error")
209 }
210 return recompMap[key]
211 }
212
213 func lookupInfoNFC(b input, i int) Properties {
214 v, sz := b.charinfoNFC(i)
215 return compInfo(v, sz)
216 }
217
218 func lookupInfoNFKC(b input, i int) Properties {
219 v, sz := b.charinfoNFKC(i)
220 return compInfo(v, sz)
221 }
222
223
224 func (f Form) Properties(s []byte) Properties {
225 if f == NFC || f == NFD {
226 return compInfo(nfcData.lookup(s))
227 }
228 return compInfo(nfkcData.lookup(s))
229 }
230
231
232 func (f Form) PropertiesString(s string) Properties {
233 if f == NFC || f == NFD {
234 return compInfo(nfcData.lookupString(s))
235 }
236 return compInfo(nfkcData.lookupString(s))
237 }
238
239
240
241
242 func compInfo(v uint16, sz int) Properties {
243 if v == 0 {
244 return Properties{size: uint8(sz)}
245 } else if v >= 0x8000 {
246 p := Properties{
247 size: uint8(sz),
248 ccc: uint8(v),
249 tccc: uint8(v),
250 flags: qcInfo(v >> 8),
251 }
252 if p.ccc > 0 || p.combinesBackward() {
253 p.nLead = uint8(p.flags & 0x3)
254 }
255 return p
256 }
257
258 h := decomps[v]
259 f := (qcInfo(h&headerFlagsMask) >> 2) | 0x4
260 p := Properties{size: uint8(sz), flags: f, index: v}
261 if v >= firstCCC {
262 v += uint16(h&headerLenMask) + 1
263 c := decomps[v]
264 p.tccc = c >> 2
265 p.flags |= qcInfo(c & 0x3)
266 if v >= firstLeadingCCC {
267 p.nLead = c & 0x3
268 if v >= firstStarterWithNLead {
269
270 p.flags &= 0x03
271 p.index = 0
272 return p
273 }
274 p.ccc = decomps[v+1]
275 }
276 }
277 return p
278 }
279
View as plain text