github.com/mavryk-network/mvgo@v1.19.9/mavryk/set.go (about) 1 // Copyright (c) 2020-2023 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc 3 4 package mavryk 5 6 import ( 7 "github.com/mavryk-network/mvgo/hash" 8 ) 9 10 type AddressSet struct { 11 set map[uint64]Address 12 coll []Address 13 } 14 15 func NewAddressSet(addrs ...Address) *AddressSet { 16 set := &AddressSet{ 17 set: make(map[uint64]Address, len(addrs)), 18 } 19 for _, v := range addrs { 20 if !v.IsValid() { 21 continue 22 } 23 set.AddUnique(v) 24 } 25 return set 26 } 27 28 func BuildAddressSet(s ...string) (*AddressSet, error) { 29 set := NewAddressSet() 30 for _, v := range s { 31 addr, err := ParseAddress(v) 32 if err != nil { 33 return nil, err 34 } 35 set.AddUnique(addr) 36 } 37 return set, nil 38 } 39 40 func MustBuildAddressSet(s ...string) *AddressSet { 41 set, err := BuildAddressSet(s...) 42 if err != nil { 43 panic(err) 44 } 45 return set 46 } 47 48 func (s *AddressSet) AddUnique(addr Address) bool { 49 h := hash.Hash64(addr[:]) 50 a, ok := s.set[h] 51 if ok { 52 if !a.Equal(addr) { 53 // hash collision 54 s.coll = append(s.coll, addr.Clone()) 55 ok = false 56 } 57 } else { 58 s.set[h] = addr.Clone() 59 } 60 return !ok 61 } 62 63 func (s *AddressSet) Add(addr Address) { 64 s.AddUnique(addr) 65 } 66 67 func (s *AddressSet) Remove(addr Address) { 68 delete(s.set, hash.Hash64(addr[:])) 69 for i := range s.coll { 70 if !s.coll[i].Equal(addr) { 71 continue 72 } 73 s.coll = append(s.coll[:i], s.coll[i+1:]...) 74 return 75 } 76 } 77 78 func (s *AddressSet) Clear() { 79 for n := range s.set { 80 delete(s.set, n) 81 } 82 s.coll = s.coll[:0] 83 } 84 85 func (s *AddressSet) Contains(addr Address) bool { 86 if s == nil || len(s.set) == 0 { 87 return false 88 } 89 a, ok := s.set[hash.Hash64(addr[:])] 90 if !ok { 91 return false 92 } 93 if a.Equal(addr) { 94 return true 95 } 96 for _, v := range s.coll { 97 if v.Equal(addr) { 98 return true 99 } 100 } 101 return false 102 } 103 104 func (s *AddressSet) Merge(b *AddressSet) { 105 for bHash, bAddr := range b.set { 106 if aAddr, ok := s.set[bHash]; ok { 107 if !aAddr.Equal(bAddr) { 108 var found bool 109 for _, v := range s.coll { 110 if v.Equal(bAddr) { 111 found = true 112 break 113 } 114 } 115 if !found { 116 s.coll = append(s.coll, bAddr) 117 } 118 } 119 } else { 120 s.set[bHash] = bAddr.Clone() 121 } 122 } 123 } 124 125 func (s *AddressSet) Len() int { 126 return len(s.set) + len(s.coll) 127 } 128 129 func (s AddressSet) Map() map[uint64]Address { 130 return s.set 131 } 132 133 func (s AddressSet) HasCollisions() bool { 134 return len(s.coll) > 0 135 } 136 137 func (s AddressSet) Slice() []Address { 138 if len(s.set) == 0 { 139 return nil 140 } 141 a := make([]Address, 0, len(s.set)) 142 for _, v := range s.Map() { 143 a = append(a, v) 144 } 145 a = append(a, s.coll...) 146 return a 147 } 148 149 func (s AddressSet) HasIntersect(t *AddressSet) bool { 150 for k, v := range s.set { 151 a, ok := t.set[k] 152 if !ok { 153 continue 154 } 155 if v.Equal(a) { 156 return true 157 } 158 for _, v := range t.coll { 159 if v.Equal(a) { 160 return true 161 } 162 } 163 } 164 for _, v := range s.coll { 165 if t.Contains(v) { 166 return true 167 } 168 } 169 return false 170 } 171 172 func (s AddressSet) Intersect(t *AddressSet) *AddressSet { 173 i := NewAddressSet() 174 for k, v := range s.set { 175 a, ok := t.set[k] 176 if !ok { 177 continue 178 } 179 if v.Equal(a) { 180 i.AddUnique(a) 181 } else { 182 for _, a := range t.coll { 183 if v.Equal(a) { 184 i.AddUnique(a) 185 } 186 } 187 } 188 } 189 for _, v := range s.coll { 190 if t.Contains(v) { 191 i.AddUnique(v) 192 } 193 } 194 return i 195 }