1/* 2 * MinIO Go Library for Amazon S3 Compatible Cloud Storage 3 * Copyright 2015-2017 MinIO, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package set 19 20import ( 21 "encoding/json" 22 "fmt" 23 "sort" 24) 25 26// StringSet - uses map as set of strings. 27type StringSet map[string]struct{} 28 29// ToSlice - returns StringSet as string slice. 30func (set StringSet) ToSlice() []string { 31 keys := make([]string, 0, len(set)) 32 for k := range set { 33 keys = append(keys, k) 34 } 35 sort.Strings(keys) 36 return keys 37} 38 39// IsEmpty - returns whether the set is empty or not. 40func (set StringSet) IsEmpty() bool { 41 return len(set) == 0 42} 43 44// Add - adds string to the set. 45func (set StringSet) Add(s string) { 46 set[s] = struct{}{} 47} 48 49// Remove - removes string in the set. It does nothing if string does not exist in the set. 50func (set StringSet) Remove(s string) { 51 delete(set, s) 52} 53 54// Contains - checks if string is in the set. 55func (set StringSet) Contains(s string) bool { 56 _, ok := set[s] 57 return ok 58} 59 60// FuncMatch - returns new set containing each value who passes match function. 61// A 'matchFn' should accept element in a set as first argument and 62// 'matchString' as second argument. The function can do any logic to 63// compare both the arguments and should return true to accept element in 64// a set to include in output set else the element is ignored. 65func (set StringSet) FuncMatch(matchFn func(string, string) bool, matchString string) StringSet { 66 nset := NewStringSet() 67 for k := range set { 68 if matchFn(k, matchString) { 69 nset.Add(k) 70 } 71 } 72 return nset 73} 74 75// ApplyFunc - returns new set containing each value processed by 'applyFn'. 76// A 'applyFn' should accept element in a set as a argument and return 77// a processed string. The function can do any logic to return a processed 78// string. 79func (set StringSet) ApplyFunc(applyFn func(string) string) StringSet { 80 nset := NewStringSet() 81 for k := range set { 82 nset.Add(applyFn(k)) 83 } 84 return nset 85} 86 87// Equals - checks whether given set is equal to current set or not. 88func (set StringSet) Equals(sset StringSet) bool { 89 // If length of set is not equal to length of given set, the 90 // set is not equal to given set. 91 if len(set) != len(sset) { 92 return false 93 } 94 95 // As both sets are equal in length, check each elements are equal. 96 for k := range set { 97 if _, ok := sset[k]; !ok { 98 return false 99 } 100 } 101 102 return true 103} 104 105// Intersection - returns the intersection with given set as new set. 106func (set StringSet) Intersection(sset StringSet) StringSet { 107 nset := NewStringSet() 108 for k := range set { 109 if _, ok := sset[k]; ok { 110 nset.Add(k) 111 } 112 } 113 114 return nset 115} 116 117// Difference - returns the difference with given set as new set. 118func (set StringSet) Difference(sset StringSet) StringSet { 119 nset := NewStringSet() 120 for k := range set { 121 if _, ok := sset[k]; !ok { 122 nset.Add(k) 123 } 124 } 125 126 return nset 127} 128 129// Union - returns the union with given set as new set. 130func (set StringSet) Union(sset StringSet) StringSet { 131 nset := NewStringSet() 132 for k := range set { 133 nset.Add(k) 134 } 135 136 for k := range sset { 137 nset.Add(k) 138 } 139 140 return nset 141} 142 143// MarshalJSON - converts to JSON data. 144func (set StringSet) MarshalJSON() ([]byte, error) { 145 return json.Marshal(set.ToSlice()) 146} 147 148// UnmarshalJSON - parses JSON data and creates new set with it. 149// If 'data' contains JSON string array, the set contains each string. 150// If 'data' contains JSON string, the set contains the string as one element. 151// If 'data' contains Other JSON types, JSON parse error is returned. 152func (set *StringSet) UnmarshalJSON(data []byte) error { 153 sl := []string{} 154 var err error 155 if err = json.Unmarshal(data, &sl); err == nil { 156 *set = make(StringSet) 157 for _, s := range sl { 158 set.Add(s) 159 } 160 } else { 161 var s string 162 if err = json.Unmarshal(data, &s); err == nil { 163 *set = make(StringSet) 164 set.Add(s) 165 } 166 } 167 168 return err 169} 170 171// String - returns printable string of the set. 172func (set StringSet) String() string { 173 return fmt.Sprintf("%s", set.ToSlice()) 174} 175 176// NewStringSet - creates new string set. 177func NewStringSet() StringSet { 178 return make(StringSet) 179} 180 181// CreateStringSet - creates new string set with given string values. 182func CreateStringSet(sl ...string) StringSet { 183 set := make(StringSet) 184 for _, k := range sl { 185 set.Add(k) 186 } 187 return set 188} 189 190// CopyStringSet - returns copy of given set. 191func CopyStringSet(set StringSet) StringSet { 192 nset := NewStringSet() 193 for k, v := range set { 194 nset[k] = v 195 } 196 return nset 197} 198