github.com/atsaki/terraform@v0.4.3-0.20150919165407-25bba5967654/helper/schema/set.go (about) 1 package schema 2 3 import ( 4 "fmt" 5 "reflect" 6 "sort" 7 "sync" 8 9 "github.com/hashicorp/terraform/helper/hashcode" 10 ) 11 12 // HashString hashes strings. If you want a Set of strings, this is the 13 // SchemaSetFunc you want. 14 func HashString(v interface{}) int { 15 return hashcode.String(v.(string)) 16 } 17 18 // Set is a set data structure that is returned for elements of type 19 // TypeSet. 20 type Set struct { 21 F SchemaSetFunc 22 23 m map[int]interface{} 24 once sync.Once 25 } 26 27 // NewSet is a convenience method for creating a new set with the given 28 // items. 29 func NewSet(f SchemaSetFunc, items []interface{}) *Set { 30 s := &Set{F: f} 31 for _, i := range items { 32 s.Add(i) 33 } 34 35 return s 36 } 37 38 // CopySet returns a copy of another set. 39 func CopySet(otherSet *Set) *Set { 40 return NewSet(otherSet.F, otherSet.List()) 41 } 42 43 // Add adds an item to the set if it isn't already in the set. 44 func (s *Set) Add(item interface{}) { 45 s.add(item) 46 } 47 48 // Remove removes an item if it's already in the set. Idempotent. 49 func (s *Set) Remove(item interface{}) { 50 s.remove(item) 51 } 52 53 // Contains checks if the set has the given item. 54 func (s *Set) Contains(item interface{}) bool { 55 _, ok := s.m[s.hash(item)] 56 return ok 57 } 58 59 // Len returns the amount of items in the set. 60 func (s *Set) Len() int { 61 return len(s.m) 62 } 63 64 // List returns the elements of this set in slice format. 65 // 66 // The order of the returned elements is deterministic. Given the same 67 // set, the order of this will always be the same. 68 func (s *Set) List() []interface{} { 69 result := make([]interface{}, len(s.m)) 70 for i, k := range s.listCode() { 71 result[i] = s.m[k] 72 } 73 74 return result 75 } 76 77 // Difference performs a set difference of the two sets, returning 78 // a new third set that has only the elements unique to this set. 79 func (s *Set) Difference(other *Set) *Set { 80 result := &Set{F: s.F} 81 result.once.Do(result.init) 82 83 for k, v := range s.m { 84 if _, ok := other.m[k]; !ok { 85 result.m[k] = v 86 } 87 } 88 89 return result 90 } 91 92 // Intersection performs the set intersection of the two sets 93 // and returns a new third set. 94 func (s *Set) Intersection(other *Set) *Set { 95 result := &Set{F: s.F} 96 result.once.Do(result.init) 97 98 for k, v := range s.m { 99 if _, ok := other.m[k]; ok { 100 result.m[k] = v 101 } 102 } 103 104 return result 105 } 106 107 // Union performs the set union of the two sets and returns a new third 108 // set. 109 func (s *Set) Union(other *Set) *Set { 110 result := &Set{F: s.F} 111 result.once.Do(result.init) 112 113 for k, v := range s.m { 114 result.m[k] = v 115 } 116 for k, v := range other.m { 117 result.m[k] = v 118 } 119 120 return result 121 } 122 123 func (s *Set) Equal(raw interface{}) bool { 124 other, ok := raw.(*Set) 125 if !ok { 126 return false 127 } 128 129 return reflect.DeepEqual(s.m, other.m) 130 } 131 132 func (s *Set) GoString() string { 133 return fmt.Sprintf("*Set(%#v)", s.m) 134 } 135 136 func (s *Set) init() { 137 s.m = make(map[int]interface{}) 138 } 139 140 func (s *Set) add(item interface{}) int { 141 s.once.Do(s.init) 142 143 code := s.hash(item) 144 if _, ok := s.m[code]; !ok { 145 s.m[code] = item 146 } 147 148 return code 149 } 150 151 func (s *Set) hash(item interface{}) int { 152 code := s.F(item) 153 // Always return a nonnegative hashcode. 154 if code < 0 { 155 return -code 156 } 157 return code 158 } 159 160 func (s *Set) remove(item interface{}) int { 161 s.once.Do(s.init) 162 163 code := s.F(item) 164 delete(s.m, code) 165 166 return code 167 } 168 169 func (s *Set) index(item interface{}) int { 170 return sort.SearchInts(s.listCode(), s.hash(item)) 171 } 172 173 func (s *Set) listCode() []int { 174 // Sort the hash codes so the order of the list is deterministic 175 keys := make([]int, 0, len(s.m)) 176 for k, _ := range s.m { 177 keys = append(keys, k) 178 } 179 sort.Sort(sort.IntSlice(keys)) 180 return keys 181 }