OSDN Git Service

new repo
[bytom/vapor.git] / vendor / gopkg.in / fatih / set.v0 / set_ts.go
1 package set
2
3 import (
4         "sync"
5 )
6
7 // Set defines a thread safe set data structure.
8 type Set struct {
9         set
10         l sync.RWMutex // we name it because we don't want to expose it
11 }
12
13 // New creates and initialize a new Set. It's accept a variable number of
14 // arguments to populate the initial set. If nothing passed a Set with zero
15 // size is created.
16 func New(items ...interface{}) *Set {
17         s := &Set{}
18         s.m = make(map[interface{}]struct{})
19
20         // Ensure interface compliance
21         var _ Interface = s
22
23         s.Add(items...)
24         return s
25 }
26
27 // New creates and initalizes a new Set interface. It accepts a variable
28 // number of arguments to populate the initial set. If nothing is passed a
29 // zero size Set based on the struct is created.
30 func (s *Set) New(items ...interface{}) Interface {
31         return New(items...)
32 }
33
34 // Add includes the specified items (one or more) to the set. The underlying
35 // Set s is modified. If passed nothing it silently returns.
36 func (s *Set) Add(items ...interface{}) {
37         if len(items) == 0 {
38                 return
39         }
40
41         s.l.Lock()
42         defer s.l.Unlock()
43
44         for _, item := range items {
45                 s.m[item] = keyExists
46         }
47 }
48
49 // Remove deletes the specified items from the set.  The underlying Set s is
50 // modified. If passed nothing it silently returns.
51 func (s *Set) Remove(items ...interface{}) {
52         if len(items) == 0 {
53                 return
54         }
55
56         s.l.Lock()
57         defer s.l.Unlock()
58
59         for _, item := range items {
60                 delete(s.m, item)
61         }
62 }
63
64 // Pop  deletes and return an item from the set. The underlying Set s is
65 // modified. If set is empty, nil is returned.
66 func (s *Set) Pop() interface{} {
67         s.l.RLock()
68         for item := range s.m {
69                 s.l.RUnlock()
70                 s.l.Lock()
71                 delete(s.m, item)
72                 s.l.Unlock()
73                 return item
74         }
75         s.l.RUnlock()
76         return nil
77 }
78
79 // Has looks for the existence of items passed. It returns false if nothing is
80 // passed. For multiple items it returns true only if all of  the items exist.
81 func (s *Set) Has(items ...interface{}) bool {
82         // assume checked for empty item, which not exist
83         if len(items) == 0 {
84                 return false
85         }
86
87         s.l.RLock()
88         defer s.l.RUnlock()
89
90         has := true
91         for _, item := range items {
92                 if _, has = s.m[item]; !has {
93                         break
94                 }
95         }
96         return has
97 }
98
99 // Size returns the number of items in a set.
100 func (s *Set) Size() int {
101         s.l.RLock()
102         defer s.l.RUnlock()
103
104         l := len(s.m)
105         return l
106 }
107
108 // Clear removes all items from the set.
109 func (s *Set) Clear() {
110         s.l.Lock()
111         defer s.l.Unlock()
112
113         s.m = make(map[interface{}]struct{})
114 }
115
116 // IsEqual test whether s and t are the same in size and have the same items.
117 func (s *Set) IsEqual(t Interface) bool {
118         s.l.RLock()
119         defer s.l.RUnlock()
120
121         // Force locking only if given set is threadsafe.
122         if conv, ok := t.(*Set); ok {
123                 conv.l.RLock()
124                 defer conv.l.RUnlock()
125         }
126
127         // return false if they are no the same size
128         if sameSize := len(s.m) == t.Size(); !sameSize {
129                 return false
130         }
131
132         equal := true
133         t.Each(func(item interface{}) bool {
134                 _, equal = s.m[item]
135                 return equal // if false, Each() will end
136         })
137
138         return equal
139 }
140
141 // IsSubset tests whether t is a subset of s.
142 func (s *Set) IsSubset(t Interface) (subset bool) {
143         s.l.RLock()
144         defer s.l.RUnlock()
145
146         subset = true
147
148         t.Each(func(item interface{}) bool {
149                 _, subset = s.m[item]
150                 return subset
151         })
152
153         return
154 }
155
156 // Each traverses the items in the Set, calling the provided function for each
157 // set member. Traversal will continue until all items in the Set have been
158 // visited, or if the closure returns false.
159 func (s *Set) Each(f func(item interface{}) bool) {
160         s.l.RLock()
161         defer s.l.RUnlock()
162
163         for item := range s.m {
164                 if !f(item) {
165                         break
166                 }
167         }
168 }
169
170 // List returns a slice of all items. There is also StringSlice() and
171 // IntSlice() methods for returning slices of type string or int.
172 func (s *Set) List() []interface{} {
173         s.l.RLock()
174         defer s.l.RUnlock()
175
176         list := make([]interface{}, 0, len(s.m))
177
178         for item := range s.m {
179                 list = append(list, item)
180         }
181
182         return list
183 }
184
185 // Copy returns a new Set with a copy of s.
186 func (s *Set) Copy() Interface {
187         return New(s.List()...)
188 }
189
190 // Merge is like Union, however it modifies the current set it's applied on
191 // with the given t set.
192 func (s *Set) Merge(t Interface) {
193         s.l.Lock()
194         defer s.l.Unlock()
195
196         t.Each(func(item interface{}) bool {
197                 s.m[item] = keyExists
198                 return true
199         })
200 }