-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathprefixmap.go
62 lines (58 loc) · 1.27 KB
/
prefixmap.go
1
2
3
4
5
6
7
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package unfurlist
import "sort"
// prefixMap allows fast checks against predefined set of prefixes.
// Uninitialized/empty prefixMap considers any string as matching.
type prefixMap struct {
prefixes map[string]struct{}
lengths []int // sorted, smaller first
}
// newPrefixMap initializes new prefixMap from given slice of prefixes
func newPrefixMap(prefixes []string) *prefixMap {
if len(prefixes) == 0 {
return nil
}
m := make(map[string]struct{}, len(prefixes))
l1 := make([]int, 0, len(prefixes))
for _, p := range prefixes {
if p == "" {
continue
}
m[p] = struct{}{}
l1 = append(l1, len(p))
}
if len(l1) == 0 {
return nil
}
sort.Ints(l1)
// remove duplicates
l2 := l1[:1]
for i := 1; i < len(l1); i++ {
if l1[i] != l1[i-1] {
l2 = append(l2, l1[i])
}
}
return &prefixMap{
prefixes: m,
lengths: l2,
}
}
// Match validates string against set of prefixes. It returns true only if
// prefixMap is non-empty and string matches at least one prefix.
func (m *prefixMap) Match(url string) bool {
if m == nil || m.prefixes == nil {
return false
}
sLen := len(url)
if sLen < m.lengths[0] {
return false
}
for _, x := range m.lengths {
if sLen < x {
continue
}
if _, ok := m.prefixes[url[:x]]; ok {
return true
}
}
return false
}