github.com/m4gshm/gollections@v0.0.10/map_/iter.go (about) 1 package map_ 2 3 import ( 4 "unsafe" 5 6 "github.com/m4gshm/gollections/c" 7 "github.com/m4gshm/gollections/kv" 8 "github.com/m4gshm/gollections/loop" 9 "github.com/m4gshm/gollections/op" 10 ) 11 12 // NewIter returns the Iter based on map elements 13 func NewIter[K comparable, V any](elements map[K]V) Iter[K, V] { 14 hmap := *(*unsafe.Pointer)(unsafe.Pointer(&elements)) 15 i := any(elements) 16 maptype := *(*unsafe.Pointer)(unsafe.Pointer(&i)) 17 var iterator *hiter 18 if hmap != nil { 19 iterator = new(hiter) 20 } 21 return Iter[K, V]{maptype: maptype, hmap: hmap, size: len(elements), iterator: iterator} 22 } 23 24 // Iter is the embedded map based Iterator implementation 25 type Iter[K comparable, V any] struct { 26 iterator *hiter 27 maptype unsafe.Pointer 28 hmap unsafe.Pointer 29 size int 30 } 31 32 var _ kv.Iterator[int, any] = (*Iter[int, any])(nil) 33 var _ kv.IterFor[int, any, *Iter[int, any]] = (*Iter[int, any])(nil) 34 35 // Track takes key, value pairs retrieved by the iterator. Can be interrupt by returning ErrBreak 36 func (i *Iter[K, V]) Track(traker func(key K, value V) error) error { 37 return loop.Track(i.Next, traker) 38 } 39 40 // TrackEach takes all key, value pairs retrieved by the iterator 41 func (i *Iter[K, V]) TrackEach(traker func(key K, value V)) { 42 loop.TrackEach(i.Next, traker) 43 } 44 45 // Next returns the next element. 46 // The ok result indicates whether the element was returned by the iterator. 47 // If ok == false, then the iteration must be completed. 48 func (i *Iter[K, V]) Next() (key K, value V, ok bool) { 49 if i == nil { 50 return key, value, false 51 } 52 iterator := i.iterator 53 if iterator == nil { 54 return key, value, false 55 } 56 if !iterator.initialized() { 57 mapiterinit(i.maptype, i.hmap, iterator) 58 } else { 59 mapiternext(iterator) 60 } 61 iterkey := mapiterkey(iterator) 62 if iterkey == nil { 63 return key, value, false 64 } 65 iterelem := mapiterelem(iterator) 66 key = *(*K)(iterkey) 67 value = *(*V)(iterelem) 68 return key, value, true 69 } 70 71 // Cap returns the size of the map 72 func (i *Iter[K, V]) Cap() int { 73 if i == nil { 74 return 0 75 } 76 return i.size 77 } 78 79 // Start is used with for loop construct like 'for i, val, ok := i.Start(); ok; val, ok = i.Next() { }' 80 func (i *Iter[K, V]) Start() (*Iter[K, V], K, V, bool) { 81 k, v, ok := i.Next() 82 return i, k, v, ok 83 } 84 85 //go:linkname mapiterinit reflect.mapiterinit 86 func mapiterinit(maptype, hmap unsafe.Pointer, it *hiter) 87 88 func mapiterkey(it *hiter) unsafe.Pointer { 89 return it.key 90 } 91 92 func mapiterelem(it *hiter) unsafe.Pointer { 93 return it.elem 94 } 95 96 //go:linkname mapiternext reflect.mapiternext 97 func mapiternext(it *hiter) 98 99 // hiter's structure matches runtime.hiter's structure 100 type hiter struct { 101 key unsafe.Pointer 102 elem unsafe.Pointer 103 t unsafe.Pointer 104 h unsafe.Pointer 105 buckets unsafe.Pointer 106 bptr unsafe.Pointer 107 overflow *[]unsafe.Pointer 108 oldoverflow *[]unsafe.Pointer 109 startBucket uintptr 110 offset uint8 111 wrapped bool 112 B uint8 113 i uint8 114 bucket uintptr 115 checkBucket uintptr 116 } 117 118 func (h *hiter) initialized() bool { 119 return h.t != nil 120 } 121 122 // NewKeyIter instantiates a map keys iterator 123 func NewKeyIter[K comparable, V any](uniques map[K]V) KeyIter[K, V] { 124 return KeyIter[K, V]{Iter: NewIter(uniques)} 125 } 126 127 // KeyIter is the Iterator implementation that provides iterating over keys of a key/value pairs iterator 128 type KeyIter[K comparable, V any] struct { 129 Iter[K, V] 130 } 131 132 var ( 133 _ c.Iterator[string] = (*KeyIter[string, any])(nil) 134 _ c.Iterator[string] = KeyIter[string, any]{} 135 ) 136 137 var _ c.IterFor[string, KeyIter[string, any]] = KeyIter[string, any]{} 138 139 // For takes elements retrieved by the iterator. Can be interrupt by returning ErrBreak 140 func (i KeyIter[K, V]) For(walker func(element K) error) error { 141 return loop.For(i.Next, walker) 142 } 143 144 // ForEach FlatIter all elements retrieved by the iterator 145 func (i KeyIter[K, V]) ForEach(walker func(element K)) { 146 loop.ForEach(i.Next, walker) 147 } 148 149 // Next returns the next element. 150 // The ok result indicates whether the element was returned by the iterator. 151 // If ok == false, then the iteration must be completed. 152 func (i KeyIter[K, V]) Next() (K, bool) { 153 key, _, ok := i.Iter.Next() 154 return key, ok 155 } 156 157 // Cap returns the iterator capacity 158 func (i KeyIter[K, V]) Cap() int { 159 return i.Iter.Cap() 160 } 161 162 // Start is used with for loop construct like 'for i, val, ok := i.Start(); ok; val, ok = i.Next() { }' 163 func (i KeyIter[K, V]) Start() (KeyIter[K, V], K, bool) { 164 key, _, ok := i.Iter.Next() 165 return i, key, ok 166 } 167 168 // NewValIter is the main values iterator constructor 169 func NewValIter[K comparable, V any](uniques map[K]V) ValIter[K, V] { 170 return ValIter[K, V]{Iter: NewIter(op.IfElse(uniques != nil, uniques, map[K]V{}))} 171 } 172 173 // ValIter is a map values iterator 174 type ValIter[K comparable, V any] struct { 175 Iter[K, V] 176 } 177 178 var ( 179 _ c.Iterator[any] = (*ValIter[int, any])(nil) 180 _ c.Iterator[any] = ValIter[int, any]{} 181 ) 182 183 var _ c.IterFor[string, ValIter[int, string]] = ValIter[int, string]{} 184 185 // For takes elements retrieved by the iterator. Can be interrupt by returning ErrBreak 186 func (i ValIter[K, V]) For(walker func(element V) error) error { 187 return loop.For(i.Next, walker) 188 } 189 190 // ForEach FlatIter all elements retrieved by the iterator 191 func (i ValIter[K, V]) ForEach(walker func(element V)) { 192 loop.ForEach(i.Next, walker) 193 } 194 195 // Next returns the next element. 196 // The ok result indicates whether the element was returned by the iterator. 197 // If ok == false, then the iteration must be completed. 198 func (i ValIter[K, V]) Next() (V, bool) { 199 _, val, ok := i.Iter.Next() 200 return val, ok 201 } 202 203 // Cap returns the size of the map 204 func (i ValIter[K, V]) Cap() int { 205 return i.Iter.Cap() 206 } 207 208 // Start is used with for loop construct like 'for i, val, ok := i.Start(); ok; val, ok = i.Next() { }' 209 func (i ValIter[K, V]) Start() (ValIter[K, V], V, bool) { 210 _, val, ok := i.Iter.Next() 211 return i, val, ok 212 }