OSDN Git Service

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