OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / gopkg.in / fatih / set.v0 / set_ts.go
diff --git a/vendor/gopkg.in/fatih/set.v0/set_ts.go b/vendor/gopkg.in/fatih/set.v0/set_ts.go
new file mode 100644 (file)
index 0000000..50f5325
--- /dev/null
@@ -0,0 +1,200 @@
+package set
+
+import (
+       "sync"
+)
+
+// Set defines a thread safe set data structure.
+type Set struct {
+       set
+       l sync.RWMutex // we name it because we don't want to expose it
+}
+
+// New creates and initialize a new Set. It's accept a variable number of
+// arguments to populate the initial set. If nothing passed a Set with zero
+// size is created.
+func New(items ...interface{}) *Set {
+       s := &Set{}
+       s.m = make(map[interface{}]struct{})
+
+       // Ensure interface compliance
+       var _ Interface = s
+
+       s.Add(items...)
+       return s
+}
+
+// New creates and initalizes a new Set interface. It accepts a variable
+// number of arguments to populate the initial set. If nothing is passed a
+// zero size Set based on the struct is created.
+func (s *Set) New(items ...interface{}) Interface {
+       return New(items...)
+}
+
+// Add includes the specified items (one or more) to the set. The underlying
+// Set s is modified. If passed nothing it silently returns.
+func (s *Set) Add(items ...interface{}) {
+       if len(items) == 0 {
+               return
+       }
+
+       s.l.Lock()
+       defer s.l.Unlock()
+
+       for _, item := range items {
+               s.m[item] = keyExists
+       }
+}
+
+// Remove deletes the specified items from the set.  The underlying Set s is
+// modified. If passed nothing it silently returns.
+func (s *Set) Remove(items ...interface{}) {
+       if len(items) == 0 {
+               return
+       }
+
+       s.l.Lock()
+       defer s.l.Unlock()
+
+       for _, item := range items {
+               delete(s.m, item)
+       }
+}
+
+// Pop  deletes and return an item from the set. The underlying Set s is
+// modified. If set is empty, nil is returned.
+func (s *Set) Pop() interface{} {
+       s.l.RLock()
+       for item := range s.m {
+               s.l.RUnlock()
+               s.l.Lock()
+               delete(s.m, item)
+               s.l.Unlock()
+               return item
+       }
+       s.l.RUnlock()
+       return nil
+}
+
+// Has looks for the existence of items passed. It returns false if nothing is
+// passed. For multiple items it returns true only if all of  the items exist.
+func (s *Set) Has(items ...interface{}) bool {
+       // assume checked for empty item, which not exist
+       if len(items) == 0 {
+               return false
+       }
+
+       s.l.RLock()
+       defer s.l.RUnlock()
+
+       has := true
+       for _, item := range items {
+               if _, has = s.m[item]; !has {
+                       break
+               }
+       }
+       return has
+}
+
+// Size returns the number of items in a set.
+func (s *Set) Size() int {
+       s.l.RLock()
+       defer s.l.RUnlock()
+
+       l := len(s.m)
+       return l
+}
+
+// Clear removes all items from the set.
+func (s *Set) Clear() {
+       s.l.Lock()
+       defer s.l.Unlock()
+
+       s.m = make(map[interface{}]struct{})
+}
+
+// IsEqual test whether s and t are the same in size and have the same items.
+func (s *Set) IsEqual(t Interface) bool {
+       s.l.RLock()
+       defer s.l.RUnlock()
+
+       // Force locking only if given set is threadsafe.
+       if conv, ok := t.(*Set); ok {
+               conv.l.RLock()
+               defer conv.l.RUnlock()
+       }
+
+       // return false if they are no the same size
+       if sameSize := len(s.m) == t.Size(); !sameSize {
+               return false
+       }
+
+       equal := true
+       t.Each(func(item interface{}) bool {
+               _, equal = s.m[item]
+               return equal // if false, Each() will end
+       })
+
+       return equal
+}
+
+// IsSubset tests whether t is a subset of s.
+func (s *Set) IsSubset(t Interface) (subset bool) {
+       s.l.RLock()
+       defer s.l.RUnlock()
+
+       subset = true
+
+       t.Each(func(item interface{}) bool {
+               _, subset = s.m[item]
+               return subset
+       })
+
+       return
+}
+
+// Each traverses the items in the Set, calling the provided function for each
+// set member. Traversal will continue until all items in the Set have been
+// visited, or if the closure returns false.
+func (s *Set) Each(f func(item interface{}) bool) {
+       s.l.RLock()
+       defer s.l.RUnlock()
+
+       for item := range s.m {
+               if !f(item) {
+                       break
+               }
+       }
+}
+
+// List returns a slice of all items. There is also StringSlice() and
+// IntSlice() methods for returning slices of type string or int.
+func (s *Set) List() []interface{} {
+       s.l.RLock()
+       defer s.l.RUnlock()
+
+       list := make([]interface{}, 0, len(s.m))
+
+       for item := range s.m {
+               list = append(list, item)
+       }
+
+       return list
+}
+
+// Copy returns a new Set with a copy of s.
+func (s *Set) Copy() Interface {
+       return New(s.List()...)
+}
+
+// Merge is like Union, however it modifies the current set it's applied on
+// with the given t set.
+func (s *Set) Merge(t Interface) {
+       s.l.Lock()
+       defer s.l.Unlock()
+
+       t.Each(func(item interface{}) bool {
+               s.m[item] = keyExists
+               return true
+       })
+}