set.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. Copyright 2014 CoreOS, Inc.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package types
  14. import (
  15. "reflect"
  16. "sort"
  17. "sync"
  18. )
  19. type Set interface {
  20. Add(string)
  21. Remove(string)
  22. Contains(string) bool
  23. Equals(Set) bool
  24. Length() int
  25. Values() []string
  26. Copy() Set
  27. Sub(Set) Set
  28. }
  29. func NewUnsafeSet(values ...string) *unsafeSet {
  30. set := &unsafeSet{make(map[string]struct{})}
  31. for _, v := range values {
  32. set.Add(v)
  33. }
  34. return set
  35. }
  36. func NewThreadsafeSet(values ...string) *tsafeSet {
  37. us := NewUnsafeSet(values...)
  38. return &tsafeSet{us, sync.RWMutex{}}
  39. }
  40. type unsafeSet struct {
  41. d map[string]struct{}
  42. }
  43. // Add adds a new value to the set (no-op if the value is already present)
  44. func (us *unsafeSet) Add(value string) {
  45. us.d[value] = struct{}{}
  46. }
  47. // Remove removes the given value from the set
  48. func (us *unsafeSet) Remove(value string) {
  49. delete(us.d, value)
  50. }
  51. // Contains returns whether the set contains the given value
  52. func (us *unsafeSet) Contains(value string) (exists bool) {
  53. _, exists = us.d[value]
  54. return
  55. }
  56. // ContainsAll returns whether the set contains all given values
  57. func (us *unsafeSet) ContainsAll(values []string) bool {
  58. for _, s := range values {
  59. if !us.Contains(s) {
  60. return false
  61. }
  62. }
  63. return true
  64. }
  65. // Equals returns whether the contents of two sets are identical
  66. func (us *unsafeSet) Equals(other Set) bool {
  67. v1 := sort.StringSlice(us.Values())
  68. v2 := sort.StringSlice(other.Values())
  69. v1.Sort()
  70. v2.Sort()
  71. return reflect.DeepEqual(v1, v2)
  72. }
  73. // Length returns the number of elements in the set
  74. func (us *unsafeSet) Length() int {
  75. return len(us.d)
  76. }
  77. // Values returns the values of the Set in an unspecified order.
  78. func (us *unsafeSet) Values() (values []string) {
  79. values = make([]string, 0)
  80. for val, _ := range us.d {
  81. values = append(values, val)
  82. }
  83. return
  84. }
  85. // Copy creates a new Set containing the values of the first
  86. func (us *unsafeSet) Copy() Set {
  87. cp := NewUnsafeSet()
  88. for val, _ := range us.d {
  89. cp.Add(val)
  90. }
  91. return cp
  92. }
  93. // Sub removes all elements in other from the set
  94. func (us *unsafeSet) Sub(other Set) Set {
  95. oValues := other.Values()
  96. result := us.Copy().(*unsafeSet)
  97. for _, val := range oValues {
  98. if _, ok := result.d[val]; !ok {
  99. continue
  100. }
  101. delete(result.d, val)
  102. }
  103. return result
  104. }
  105. type tsafeSet struct {
  106. us *unsafeSet
  107. m sync.RWMutex
  108. }
  109. func (ts *tsafeSet) Add(value string) {
  110. ts.m.Lock()
  111. defer ts.m.Unlock()
  112. ts.us.Add(value)
  113. }
  114. func (ts *tsafeSet) Remove(value string) {
  115. ts.m.Lock()
  116. defer ts.m.Unlock()
  117. ts.us.Remove(value)
  118. }
  119. func (ts *tsafeSet) Contains(value string) (exists bool) {
  120. ts.m.RLock()
  121. defer ts.m.RUnlock()
  122. return ts.us.Contains(value)
  123. }
  124. func (ts *tsafeSet) Equals(other Set) bool {
  125. ts.m.RLock()
  126. defer ts.m.RUnlock()
  127. return ts.us.Equals(other)
  128. }
  129. func (ts *tsafeSet) Length() int {
  130. ts.m.RLock()
  131. defer ts.m.RUnlock()
  132. return ts.us.Length()
  133. }
  134. func (ts *tsafeSet) Values() (values []string) {
  135. ts.m.RLock()
  136. defer ts.m.RUnlock()
  137. return ts.us.Values()
  138. }
  139. func (ts *tsafeSet) Copy() Set {
  140. ts.m.RLock()
  141. defer ts.m.RUnlock()
  142. usResult := ts.us.Copy().(*unsafeSet)
  143. return &tsafeSet{usResult, sync.RWMutex{}}
  144. }
  145. func (ts *tsafeSet) Sub(other Set) Set {
  146. ts.m.RLock()
  147. defer ts.m.RUnlock()
  148. usResult := ts.us.Sub(other).(*unsafeSet)
  149. return &tsafeSet{usResult, sync.RWMutex{}}
  150. }