-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathparser.go
88 lines (75 loc) · 1.54 KB
/
parser.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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package uaparser
import (
"strings"
"unicode"
)
type itemSpec struct {
name string
mustContains []string
mustNotContains []string
versionSplitters [][]string
}
type InfoItem struct {
Name string
Version string
}
type UAInfo struct {
Browser,
Device,
DeviceType,
OS *InfoItem
}
func isEmptyString(str string) bool {
for _, char := range str {
if !unicode.IsSpace(char) {
return false
}
}
return true
}
func contains(ua string, tokens []string) bool {
for _, tk := range tokens {
if strings.Contains(ua, tk) {
return true
}
}
return false
}
func matchSpec(ua string, spec *itemSpec) (info *InfoItem, ok bool) {
if !contains(ua, spec.mustContains) {
return
}
if contains(ua, spec.mustNotContains) {
return
}
info = new(InfoItem)
info.Name = spec.name
ok = true
for _, splitter := range spec.versionSplitters {
if strings.Contains(ua, splitter[0]) {
if rmLeft := strings.Split(ua, splitter[0])[1]; strings.Contains(rmLeft, splitter[1]) || isEmptyString(splitter[1]) {
rmRight := strings.Split(rmLeft, splitter[1])[0]
info.Version = strings.TrimSpace(rmRight)
break
}
}
}
return
}
func searchIn(ua string, specs []*itemSpec) (info *InfoItem) {
for _, spec := range specs {
if result, ok := matchSpec(ua, spec); ok {
info = result
break
}
}
return
}
func Parse(ua string) (info *UAInfo) {
info = new(UAInfo)
info.Browser = searchIn(ua, _BROWSERS)
info.Device = searchIn(ua, _DEVICES)
info.DeviceType = searchIn(ua, _DEVICETYPES)
info.OS = searchIn(ua, _OS)
return
}