implemented Push and Pop

This commit is contained in:
milarin 2023-07-27 22:09:41 +02:00
parent 71ee6f3d04
commit e856ec18e1
5 changed files with 71 additions and 8 deletions

View File

@ -6,5 +6,6 @@ import (
var ( var (
ErrNothingToUnread = adverr.NewErrTmpl("ErrNothingToUnread", "Unreading failed because there wasn't any Read yet") 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") ErrNoMoreValues = adverr.NewErrTmpl("ErrNoMoreValues", "source does not have any more values")
) )

3
go.mod
View File

@ -5,4 +5,7 @@ go 1.20
require ( require (
git.milar.in/milarin/adverr v1.1.0 git.milar.in/milarin/adverr v1.1.0
git.milar.in/milarin/ds v0.0.2 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

4
go.sum
View File

@ -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/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 h1:vCA3mDxZUNfvHpzrdz7SeBUKiPn74NTopo915IUG7I0=
git.milar.in/milarin/ds v0.0.2/go.mod h1:HJK7QERcRvV9j7xzEocrKUtW+1q4JB1Ly4Bj54chfwI= 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=

View File

@ -1,10 +1,15 @@
package anyreader package anyreader
import "git.milar.in/milarin/ds" import (
"git.milar.in/milarin/ds"
"git.milar.in/milarin/slices"
)
type Reader[T any] struct { type Reader[T any] struct {
buf ds.Stack[T] buf ds.Stack[T]
src func() (T, error) indices ds.Stack[uint64]
index uint64
src func() (T, error)
} }
func NewReaderFromSlice[T any](s []T) *Reader[T] { 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] { func NewReaderFromErrorFunc[T any](src func() (T, error)) *Reader[T] {
return &Reader[T]{ return &Reader[T]{
src: src, src: src,
buf: ds.NewArrayStack[T](), 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() v, err := r.src()
if err == nil { if err == nil {
r.buf.Push(v) r.buf.Push(v)
r.index++
} }
return v, err return v, err
} }
@ -36,6 +44,7 @@ func (r *Reader[T]) Unread() error {
} }
v := r.buf.Pop() v := r.buf.Pop()
r.index--
returned := false returned := false
oldSrc := r.src oldSrc := r.src
@ -114,6 +123,44 @@ func (r *Reader[T]) Expect(f ...func(T) bool) (bool, error) {
return findFirstTrue(value, f), nil return findFirstTrue(value, f), nil
} }
func (r *Reader[T]) Commit() { func (r *Reader[T]) Push() {
r.buf.Clear() 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
} }

View File

@ -8,6 +8,14 @@ import (
func TestReader(t *testing.T) { func TestReader(t *testing.T) {
r := NewReaderFromSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) r := NewReaderFromSlice([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
fmt.Println(r.Read()) 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()) fmt.Println(r.Read())
} }