Skip to content

Commit

Permalink
Merge pull request #3 from arg0net:scan
Browse files Browse the repository at this point in the history
add Scan method
  • Loading branch information
vgough authored Jun 11, 2024
2 parents 5d45cd9 + 71814d7 commit f06fc82
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
18 changes: 18 additions & 0 deletions ring.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,21 @@ func (r *Ring[T]) Reset() {
r.right = r.elements[:0]
clear(r.elements)
}

// Scan calls the given function for each element in the ring, in order.
// If the function returns true, then the value and index of the element are returned.
// If no match is found, then returns the zero value of T and -1.
func (r *Ring[T]) Scan(fn func(T) bool) (T, int) {
for i, e := range r.right {
if fn(e) {
return e, i
}
}
for i, e := range r.left {
if fn(e) {
return e, i + len(r.right)
}
}
var zero T
return zero, -1
}
37 changes: 37 additions & 0 deletions ring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,25 @@ func TestRingIndex_Wrap(t *testing.T) {
require.Equal(t, 6, el)
}

func TestRingScan(t *testing.T) {
r := collections.NewRing[int](5)
for i := 0; i < 4; i++ {
r.PushBack(i)
}
for i := 5; i < 100; i++ {
check := i % 4
value, ok := r.PeekIndex(check)
require.True(t, ok)
found, idx := r.Scan(func(v int) bool {
return v == value
})
require.Equal(t, value, found)
require.Equal(t, check, idx)
r.PopFront()
r.PushBack(i)
}
}

func BenchmarkRing(b *testing.B) {
r := collections.NewRing[int](1024)
// fill the ring
Expand Down Expand Up @@ -201,6 +220,7 @@ const (
popFront
popIndex
peekIndex
scan
lastOpForCounting // keep last
)

Expand Down Expand Up @@ -273,6 +293,23 @@ func FuzzRing(f *testing.F) {
if f1 != r1 || ok1 != ok2 {
t.Fatalf("peekIndex differs: %v vs %v in %v vs %v", f1, r1, fake, real)
}
case scan:
var idx int
if i+1 < len(ops) {
idx = int(ops[i+1])
i++
}
t.Logf("scan %d", idx)
scanNum := 0
v, loc := real.Scan(func(v int) bool {
o := scanNum
scanNum++
return o == idx
})
v2, ok2 := real.PeekIndex(idx)
if ok2 && (loc != idx || v != v2) {
t.Fatalf("scan differs: %v vs %v in %v", v, v2, real)
}
}
if fake.Copy(buf1[:]) != real.Copy(buf2[:]) {
t.Fatalf("copy differs")
Expand Down

0 comments on commit f06fc82

Please sign in to comment.