From e856ec18e1e287617cf5d0264fcc1cc3fd6ca9c7 Mon Sep 17 00:00:00 2001 From: milarin Date: Thu, 27 Jul 2023 22:09:41 +0200 Subject: [PATCH] implemented Push and Pop --- errors.go | 1 + go.mod | 3 +++ go.sum | 4 ++++ reader.go | 61 ++++++++++++++++++++++++++++++++++++++++++++------ reader_test.go | 10 ++++++++- 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/errors.go b/errors.go index a5a653a..88913c0 100644 --- a/errors.go +++ b/errors.go @@ -6,5 +6,6 @@ import ( var ( ErrNothingToUnread = adverr.NewErrTmpl("ErrNothingToUnread", "Unreading failed because there wasn't any Read yet") + ErrPopFailed = adverr.NewErrTmpl("ErrPopFailed", "stack cannot be popped. It was never pushed") ErrNoMoreValues = adverr.NewErrTmpl("ErrNoMoreValues", "source does not have any more values") ) diff --git a/go.mod b/go.mod index e591a7f..b774133 100644 --- a/go.mod +++ b/go.mod @@ -5,4 +5,7 @@ go 1.20 require ( git.milar.in/milarin/adverr v1.1.0 git.milar.in/milarin/ds v0.0.2 + git.milar.in/milarin/slices v0.0.8 ) + +require git.milar.in/milarin/gmath v0.0.3 // indirect diff --git a/go.sum b/go.sum index bb49ff3..cabd037 100644 --- a/go.sum +++ b/go.sum @@ -2,3 +2,7 @@ git.milar.in/milarin/adverr v1.1.0 h1:jD9WnOvs40lfMhvqQ7cllOaRJNBMWr1f07/s9jAadp git.milar.in/milarin/adverr v1.1.0/go.mod h1:joU9sBb7ySyNv4SpTXB0Z4o1mjXsArBw4N27wjgzj9E= git.milar.in/milarin/ds v0.0.2 h1:vCA3mDxZUNfvHpzrdz7SeBUKiPn74NTopo915IUG7I0= git.milar.in/milarin/ds v0.0.2/go.mod h1:HJK7QERcRvV9j7xzEocrKUtW+1q4JB1Ly4Bj54chfwI= +git.milar.in/milarin/gmath v0.0.3 h1:ii6rKNItS55O/wtIFhD1cTN2BMwDZjTBmiOocKURvxM= +git.milar.in/milarin/gmath v0.0.3/go.mod h1:HDLftG5RLpiNGKiIWh+O2G1PYkNzyLDADO8Cd/1abiE= +git.milar.in/milarin/slices v0.0.8 h1:qN9TE3tkArdTixMKSnwvNPcApwAjxpLVwA5a9k1rm2s= +git.milar.in/milarin/slices v0.0.8/go.mod h1:qMhdtMnfWswc1rHpwgNw33lB84aNEkdBn5BDiYA+G3k= diff --git a/reader.go b/reader.go index 85888e8..c6c07d2 100644 --- a/reader.go +++ b/reader.go @@ -1,10 +1,15 @@ package anyreader -import "git.milar.in/milarin/ds" +import ( + "git.milar.in/milarin/ds" + "git.milar.in/milarin/slices" +) type Reader[T any] struct { - buf ds.Stack[T] - src func() (T, error) + buf ds.Stack[T] + indices ds.Stack[uint64] + index uint64 + src func() (T, error) } func NewReaderFromSlice[T any](s []T) *Reader[T] { @@ -17,8 +22,10 @@ func NewReaderFromFunc[T any](src func() T) *Reader[T] { func NewReaderFromErrorFunc[T any](src func() (T, error)) *Reader[T] { return &Reader[T]{ - src: src, - buf: ds.NewArrayStack[T](), + src: src, + buf: ds.NewArrayStack[T](), + index: 0, + indices: ds.NewArrayStack[uint64](), } } @@ -26,6 +33,7 @@ func (r *Reader[T]) Read() (T, error) { v, err := r.src() if err == nil { r.buf.Push(v) + r.index++ } return v, err } @@ -36,6 +44,7 @@ func (r *Reader[T]) Unread() error { } v := r.buf.Pop() + r.index-- returned := false oldSrc := r.src @@ -114,6 +123,44 @@ func (r *Reader[T]) Expect(f ...func(T) bool) (bool, error) { return findFirstTrue(value, f), nil } -func (r *Reader[T]) Commit() { - r.buf.Clear() +func (r *Reader[T]) Push() { + r.indices.Push(r.index) +} + +func (r *Reader[T]) Pop() ([]T, error) { + if r.indices.Empty() { + return nil, ErrPopFailed.New() + } + + lastIndex := r.indices.Pop() + currentIndex := r.index + if lastIndex < currentIndex { + values := make([]T, 0, int(currentIndex-lastIndex)) + for i := 0; i < int(currentIndex-lastIndex); i++ { + err := r.Unread() + if err != nil { + return nil, err + } + + value, err := r.Peek() + if err != nil { + return nil, err + } + + values = append(values, value) + } + return slices.Reverse(values), nil + } else if lastIndex > currentIndex { + values := make([]T, 0, int(lastIndex-currentIndex)) + for i := 0; i < int(lastIndex-currentIndex); i++ { + value, err := r.Read() + if err != nil { + return nil, err + } + values = append(values, value) + } + return values, nil + } + + return []T{}, nil } diff --git a/reader_test.go b/reader_test.go index 805a60f..d00fb0a 100644 --- a/reader_test.go +++ b/reader_test.go @@ -8,6 +8,14 @@ import ( func TestReader(t *testing.T) { r := NewReaderFromSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) fmt.Println(r.Read()) - r.Unread() + fmt.Println(r.Read()) + + r.Push() + + fmt.Println(r.Unread()) + fmt.Println(r.Unread()) + + fmt.Println(r.Pop()) + fmt.Println(r.Read()) }