diff options
Diffstat (limited to 'vendor/gopkg.in/fatih/set.v0/set_ts.go')
-rw-r--r-- | vendor/gopkg.in/fatih/set.v0/set_ts.go | 200 |
1 files changed, 200 insertions, 0 deletions
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 index 000000000..50f532565 --- /dev/null +++ b/vendor/gopkg.in/fatih/set.v0/set_ts.go @@ -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 + }) +} |