github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/queues/circularbuffer/iterator.go (about)

     1  // Copyright (c) 2021, Emir Pasic. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package circularbuffer
     6  
     7  import "github.com/songzhibin97/go-baseutils/structure/containers"
     8  
     9  // Assert Iterator implementation
    10  var _ containers.ReverseIteratorWithIndex[any] = (*Iterator[any])(nil)
    11  
    12  // Iterator returns a stateful iterator whose values can be fetched by an index.
    13  type Iterator[E any] struct {
    14  	queue *Queue[E]
    15  	index int
    16  }
    17  
    18  // Iterator returns a stateful iterator whose values can be fetched by an index.
    19  func (queue *Queue[E]) Iterator() Iterator[E] {
    20  	return Iterator[E]{queue: queue, index: -1}
    21  }
    22  
    23  // Next moves the iterator to the next element and returns true if there was a next element in the container.
    24  // If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
    25  // If Next() was called for the first time, then it will point the iterator to the first element if it exists.
    26  // Modifies the state of the iterator.
    27  func (iterator *Iterator[E]) Next() bool {
    28  	if iterator.index < iterator.queue.size {
    29  		iterator.index++
    30  	}
    31  	return iterator.queue.withinRange(iterator.index)
    32  }
    33  
    34  // Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
    35  // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
    36  // Modifies the state of the iterator.
    37  func (iterator *Iterator[E]) Prev() bool {
    38  	if iterator.index >= 0 {
    39  		iterator.index--
    40  	}
    41  	return iterator.queue.withinRange(iterator.index)
    42  }
    43  
    44  // Value returns the current element's value.
    45  // Does not modify the state of the iterator.
    46  func (iterator *Iterator[E]) Value() E {
    47  	index := (iterator.index + iterator.queue.start) % iterator.queue.maxSize
    48  	value := iterator.queue.values[index]
    49  	return value
    50  }
    51  
    52  // Index returns the current element's index.
    53  // Does not modify the state of the iterator.
    54  func (iterator *Iterator[E]) Index() int {
    55  	return iterator.index
    56  }
    57  
    58  // Begin resets the iterator to its initial state (one-before-first)
    59  // Call Next() to fetch the first element if any.
    60  func (iterator *Iterator[E]) Begin() {
    61  	iterator.index = -1
    62  }
    63  
    64  // End moves the iterator past the last element (one-past-the-end).
    65  // Call Prev() to fetch the last element if any.
    66  func (iterator *Iterator[E]) End() {
    67  	iterator.index = iterator.queue.size
    68  }
    69  
    70  // First moves the iterator to the first element and returns true if there was a first element in the container.
    71  // If First() returns true, then first element's index and value can be retrieved by Index() and Value().
    72  // Modifies the state of the iterator.
    73  func (iterator *Iterator[E]) First() bool {
    74  	iterator.Begin()
    75  	return iterator.Next()
    76  }
    77  
    78  // Last moves the iterator to the last element and returns true if there was a last element in the container.
    79  // If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
    80  // Modifies the state of the iterator.
    81  func (iterator *Iterator[E]) Last() bool {
    82  	iterator.End()
    83  	return iterator.Prev()
    84  }
    85  
    86  // NextTo moves the iterator to the next element from current position that satisfies the condition given by the
    87  // passed function, and returns true if there was a next element in the container.
    88  // If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
    89  // Modifies the state of the iterator.
    90  func (iterator *Iterator[E]) NextTo(f func(index int, value E) bool) bool {
    91  	for iterator.Next() {
    92  		index, value := iterator.Index(), iterator.Value()
    93  		if f(index, value) {
    94  			return true
    95  		}
    96  	}
    97  	return false
    98  }
    99  
   100  // PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
   101  // passed function, and returns true if there was a next element in the container.
   102  // If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
   103  // Modifies the state of the iterator.
   104  func (iterator *Iterator[E]) PrevTo(f func(index int, value E) bool) bool {
   105  	for iterator.Prev() {
   106  		index, value := iterator.Index(), iterator.Value()
   107  		if f(index, value) {
   108  			return true
   109  		}
   110  	}
   111  	return false
   112  }