-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathset.go
More file actions
112 lines (97 loc) · 2.1 KB
/
Copy pathset.go
File metadata and controls
112 lines (97 loc) · 2.1 KB
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package languages
import (
"encoding/json"
"fmt"
"math/bits"
"strconv"
)
const setWords = (int(LanguageCount) + wordBits - 1) / wordBits
// Set stores language candidates without allocation. Its zero value is empty.
type Set struct{ words [setWords]uint64 }
func NewSet(languages ...Language) (s Set) {
for _, l := range languages {
s.add(l)
}
return s
}
func (s *Set) add(l Language) {
if l > Unknown && l < LanguageCount {
s.words[l/wordBits] |= 1 << (l % wordBits)
}
}
func (s Set) Has(l Language) bool {
return l > Unknown && l < LanguageCount && s.words[l/wordBits]&(1<<(l%wordBits)) != 0
}
func (s Set) Empty() bool { return s == Set{} }
func (s Set) Len() int {
n := 0
for _, word := range s.words {
n += bits.OnesCount64(word)
}
return n
}
func (s Set) Only() Language {
if s.Len() != 1 {
return Unknown
}
return s.first()
}
func (s Set) first() Language {
for i, word := range s.words {
if word != 0 {
return Language(i*64 + bits.TrailingZeros64(word))
}
}
return Unknown
}
func (s Set) Union(other Set) Set {
for i := range s.words {
s.words[i] |= other.words[i]
}
return s
}
func (s Set) Intersect(other Set) Set {
for i := range s.words {
s.words[i] &= other.words[i]
}
return s
}
func (s Set) overlaps(other Set) bool {
for i, word := range s.words {
if word&other.words[i] != 0 {
return true
}
}
return false
}
// MarshalJSON writes candidate names, independent of numeric language indices.
func (s Set) MarshalJSON() ([]byte, error) {
data := []byte{'['}
for i, word := range s.words {
for word != 0 {
l := Language(i*64 + bits.TrailingZeros64(word))
word &= word - 1
if len(data) > 1 {
data = append(data, ',')
}
data = strconv.AppendQuote(data, l.String())
}
}
return append(data, ']'), nil
}
func (s *Set) UnmarshalJSON(data []byte) error {
var names []string
if err := json.Unmarshal(data, &names); err != nil {
return err
}
var result Set
for _, name := range names {
language := Parse(name)
if language == Unknown {
return fmt.Errorf("unknown language %q", name)
}
result.add(language)
}
*s = result
return nil
}