diff options
| -rw-r--r-- | vecdeque.go | 34 | ||||
| -rw-r--r-- | vecdeque_test.go | 41 |
2 files changed, 70 insertions, 5 deletions
diff --git a/vecdeque.go b/vecdeque.go index 94d64da..5d6cc92 100644 --- a/vecdeque.go +++ b/vecdeque.go @@ -100,6 +100,23 @@ func (q *DQ[T]) PushBack(values ...T) { q.buf = q.buf[:len(q.buf)+len(values)] } +// Reset empties the deque, retaining the underlying storage for use by +// future pushes. +func (q *DQ[T]) Reset() { + q.buf = q.buf[:0] +} + +// AvailableBuffer returns an empty slice with q.Cap()-q.Len() capacity. This +// slice is intended to be appended to and passed to an immediately succeeding +// DQ.PushBack call. The slice is only valid until the next push operation on q. +func (q *DQ[T]) AvailableBuffer() []T { + endIdx := q.toPhysicalIdx(len(q.buf)) + if endIdx <= q.head { + return q.buf[endIdx:endIdx:q.head] + } + return q.buf[endIdx:endIdx] +} + // Grow makes space for at least n more elements to be inserted in the given // deque without reallocation. func (q *DQ[T]) Grow(n int) { @@ -151,7 +168,7 @@ func (q *DQ[T]) Grow(n int) { // any elements. func (q *DQ[T]) All() func(func(int, T) bool) { return func(yield func(int, T) bool) { - for i := range q.Len() { + for i := range len(q.buf) { if !yield(i, q.Get(i)) { return } @@ -159,14 +176,21 @@ func (q *DQ[T]) All() func(func(int, T) bool) { } } -// PopAll returns an iterator that consumes all the values in the deque, leaving -// it empty. +// PopAll empties the deque and returns an iterator over the popped elements. +// It's not safe to modify the deque while iterating using PopAll. func (q *DQ[T]) PopAll() func(func(T) bool) { + n := len(q.buf) + q.buf = q.buf[:0] return func(yield func(T) bool) { - for val, ok := q.PopFront(); ok; val, ok = q.PopFront() { - if !yield(val) { + endIdx := q.toPhysicalIdx(n) + for i := q.head; ; { + if !yield(q.buf[:cap(q.buf)][i]) { return } + i = q.wrapAdd(i, 1) + if i == endIdx { + break + } } } } diff --git a/vecdeque_test.go b/vecdeque_test.go index 527c46c..a66fff4 100644 --- a/vecdeque_test.go +++ b/vecdeque_test.go @@ -1,6 +1,8 @@ package vecdeque import ( + "bytes" + "fmt" "slices" "testing" ) @@ -242,7 +244,22 @@ func TestPopFrontPushFront(t *testing.T) { } } +func TestReset(t *testing.T) { + t.Parallel() + + q := From([]int{1, 2, 3, 4, 5}) + q.Reset() + if got, want := q.Len(), 0; got != want { + t.Errorf("After Reset() Len() = %d, want %d", got, want) + } + if got, want := q.Cap(), 5; got != want { + t.Errorf("After Reset() Cap() = %d, want %d", got, want) + } +} + func TestPopAll(t *testing.T) { + t.Parallel() + q := From([]int{1, 2, 3}) got := make([]int, 0, q.Len()) for x := range q.PopAll() { @@ -256,3 +273,27 @@ func TestPopAll(t *testing.T) { t.Errorf("PopAll() returned values %d, want %d", got, want) } } + +func TestAvailableBuffer(t *testing.T) { + t.Parallel() + + const cap = 10 + q := WithCapacity[byte](cap) + q.PushBack(append(q.AvailableBuffer(), []byte(" ")...)...) + q.PushBack(fmt.Appendf(q.AvailableBuffer(), "%d", 12345)...) + for range 5 { + q.PopFront() + } + q.PushBack(fmt.Appendf(q.AvailableBuffer(), "%d", 67890)...) + if got, want := q.Cap(), cap; got != want { + t.Errorf("Cap() = %d, want %d", got, want) + } + got := make([]byte, q.Len()) + for i, x := range q.All() { + got[i] = x + } + want := []byte("1234567890") + if !bytes.Equal(got, want) { + t.Errorf("Incorrect content after appending to AvailableBuffer, got %d want %d", got, want) + } +} |
