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  }