2024-10-05 01:28:46 +02:00
|
|
|
package dataext
|
|
|
|
|
|
|
|
import "iter"
|
|
|
|
|
|
|
|
type RingBuffer[T any] struct {
|
|
|
|
items []T //
|
|
|
|
capacity int // max number of items the buffer can hold
|
|
|
|
size int // how many items are in the buffer
|
|
|
|
head int // ptr to next item
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRingBuffer[T any](capacity int) *RingBuffer[T] {
|
|
|
|
return &RingBuffer[T]{
|
|
|
|
items: make([]T, capacity),
|
|
|
|
capacity: capacity,
|
|
|
|
size: 0,
|
|
|
|
head: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Push(item T) {
|
|
|
|
if rb.size < rb.capacity {
|
|
|
|
rb.size++
|
|
|
|
}
|
|
|
|
rb.items[rb.head] = item
|
|
|
|
rb.head = (rb.head + 1) % rb.capacity
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Peek() (T, bool) {
|
|
|
|
if rb.size == 0 {
|
|
|
|
return *new(T), false
|
|
|
|
}
|
|
|
|
return rb.items[(rb.head-1+rb.capacity)%rb.capacity], true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Items() []T {
|
|
|
|
if rb.size < rb.capacity {
|
|
|
|
return rb.items[:rb.size]
|
|
|
|
}
|
|
|
|
return append(rb.items[rb.head:], rb.items[:rb.head]...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Size() int {
|
|
|
|
return rb.size
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Capacity() int {
|
|
|
|
return rb.capacity
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Clear() {
|
|
|
|
rb.size = 0
|
|
|
|
rb.head = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) IsFull() bool {
|
|
|
|
return rb.size == rb.capacity
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) At(i int) T {
|
|
|
|
if i < 0 || i >= rb.size {
|
|
|
|
panic("Index out of bounds")
|
|
|
|
}
|
2024-10-05 01:41:10 +02:00
|
|
|
if rb.size < rb.capacity {
|
|
|
|
return rb.items[i]
|
|
|
|
}
|
2024-10-05 01:28:46 +02:00
|
|
|
return rb.items[(rb.head+i)%rb.capacity]
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Get(i int) (T, bool) {
|
|
|
|
if i < 0 || i >= rb.size {
|
|
|
|
return *new(T), false
|
|
|
|
}
|
2024-10-05 01:41:10 +02:00
|
|
|
if rb.size < rb.capacity {
|
|
|
|
return rb.items[i], true
|
|
|
|
}
|
2024-10-05 01:28:46 +02:00
|
|
|
return rb.items[(rb.head+i)%rb.capacity], true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Iter() iter.Seq[T] {
|
|
|
|
return func(yield func(T) bool) {
|
|
|
|
for i := 0; i < rb.size; i++ {
|
|
|
|
if !yield(rb.At(i)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (rb *RingBuffer[T]) Iter2() iter.Seq2[int, T] {
|
|
|
|
return func(yield func(int, T) bool) {
|
|
|
|
for i := 0; i < rb.size; i++ {
|
|
|
|
if !yield(i, rb.At(i)) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|