...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package search
17
18 import (
19 "strings"
20
21 "golang.org/x/text/internal/colltab"
22 "golang.org/x/text/language"
23 )
24
25
26 type Option func(*Matcher)
27
28 var (
29
30
31 WholeWord Option = nil
32
33
34
35 Exact Option = nil
36
37
38 Loose Option = loose
39
40
41 IgnoreCase Option = ignoreCase
42
43
44 IgnoreDiacritics Option = ignoreDiacritics
45
46
47 IgnoreWidth Option = ignoreWidth
48 )
49
50 func ignoreDiacritics(m *Matcher) { m.ignoreDiacritics = true }
51 func ignoreCase(m *Matcher) { m.ignoreCase = true }
52 func ignoreWidth(m *Matcher) { m.ignoreWidth = true }
53 func loose(m *Matcher) {
54 ignoreDiacritics(m)
55 ignoreCase(m)
56 ignoreWidth(m)
57 }
58
59 var (
60
61 Supported language.Coverage
62
63 tags []language.Tag
64 )
65
66 func init() {
67 ids := strings.Split(availableLocales, ",")
68 tags = make([]language.Tag, len(ids))
69 for i, s := range ids {
70 tags[i] = language.Raw.MustParse(s)
71 }
72 Supported = language.NewCoverage(tags)
73 }
74
75
76 func New(t language.Tag, opts ...Option) *Matcher {
77 m := &Matcher{
78 w: getTable(locales[colltab.MatchLang(t, tags)]),
79 }
80 for _, f := range opts {
81 f(m)
82 }
83 return m
84 }
85
86
87 type Matcher struct {
88 w colltab.Weighter
89 ignoreCase bool
90 ignoreWidth bool
91 ignoreDiacritics bool
92 }
93
94
95
96 type IndexOption byte
97
98 const (
99
100
101 Anchor IndexOption = 1 << iota
102
103
104 Backwards
105
106 anchorBackwards = Anchor | Backwards
107 )
108
109
110
111 func (m *Matcher) Index(b, pat []byte, opts ...IndexOption) (start, end int) {
112
113 return m.Compile(pat).Index(b, opts...)
114 }
115
116
117
118 func (m *Matcher) IndexString(s, pat string, opts ...IndexOption) (start, end int) {
119
120 return m.CompileString(pat).IndexString(s, opts...)
121 }
122
123
124 func (m *Matcher) Equal(a, b []byte) bool {
125 _, end := m.Index(a, b, Anchor)
126 return end == len(a)
127 }
128
129
130 func (m *Matcher) EqualString(a, b string) bool {
131 _, end := m.IndexString(a, b, Anchor)
132 return end == len(a)
133 }
134
135
136 func (m *Matcher) Compile(b []byte) *Pattern {
137 p := &Pattern{m: m}
138 iter := colltab.Iter{Weighter: m.w}
139 for iter.SetInput(b); iter.Next(); {
140 }
141 p.ce = iter.Elems
142 p.deleteEmptyElements()
143 return p
144 }
145
146
147
148 func (m *Matcher) CompileString(s string) *Pattern {
149 p := &Pattern{m: m}
150 iter := colltab.Iter{Weighter: m.w}
151 for iter.SetInputString(s); iter.Next(); {
152 }
153 p.ce = iter.Elems
154 p.deleteEmptyElements()
155 return p
156 }
157
158
159 type Pattern struct {
160 m *Matcher
161 ce []colltab.Elem
162 }
163
164
165
166
167
168
169
170
171 func (p *Pattern) Index(b []byte, opts ...IndexOption) (start, end int) {
172
173
174 var buf [8]colltab.Elem
175
176 it := &colltab.Iter{
177 Weighter: p.m.w,
178 Elems: buf[:0],
179 }
180 it.SetInput(b)
181
182 var optMask IndexOption
183 for _, o := range opts {
184 optMask |= o
185 }
186
187 switch optMask {
188 case 0:
189 return p.forwardSearch(it)
190 case Anchor:
191 return p.anchoredForwardSearch(it)
192 case Backwards, anchorBackwards:
193 panic("TODO: implement")
194 default:
195 panic("unrecognized option")
196 }
197 }
198
199
200
201 func (p *Pattern) IndexString(s string, opts ...IndexOption) (start, end int) {
202
203
204 var buf [8]colltab.Elem
205
206 it := &colltab.Iter{
207 Weighter: p.m.w,
208 Elems: buf[:0],
209 }
210 it.SetInputString(s)
211
212 var optMask IndexOption
213 for _, o := range opts {
214 optMask |= o
215 }
216
217 switch optMask {
218 case 0:
219 return p.forwardSearch(it)
220 case Anchor:
221 return p.anchoredForwardSearch(it)
222 case Backwards, anchorBackwards:
223 panic("TODO: implement")
224 default:
225 panic("unrecognized option")
226 }
227 }
228
229
230
231
232
233
234
235
236
237
238
View as plain text