expr/list-iterator.go

150 lines
3.0 KiB
Go

// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// list-iterator.go
package expr
import (
"fmt"
"io"
"slices"
"git.portale-stac.it/go-pkg/expr/kern"
)
type ListIterator struct {
a *kern.ListType
count int
index int
start int
stop int
step int
}
func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) {
var argc int = 0
listLen := len(([]any)(*list))
if args != nil {
argc = len(args)
}
it = &ListIterator{a: list, count: 0, index: -1, start: 0, stop: listLen - 1, step: 1}
if argc >= 1 {
if i, err := kern.ToGoInt(args[0], "start index"); err == nil {
if i < 0 {
i = listLen + i
}
it.start = i
}
if argc >= 2 {
if i, err := kern.ToGoInt(args[1], "stop index"); err == nil {
if i < 0 {
i = listLen + i
}
it.stop = i
}
if argc >= 3 {
if i, err := kern.ToGoInt(args[2], "step"); err == nil {
if i < 0 {
i = -i
}
if it.start > it.stop {
it.step = -i
} else {
it.step = i
}
}
}
}
}
it.index = it.start - it.step
return
}
func NewArrayIterator(array []any) (it *ListIterator) {
it = &ListIterator{a: (*kern.ListType)(&array), count: 0, index: -1, start: 0, stop: len(array) - 1, step: 1}
return
}
func (it *ListIterator) String() string {
var l = 0
if it.a != nil {
l = len(*it.a)
}
return fmt.Sprintf("$([#%d])", l)
}
func (it *ListIterator) TypeName() string {
return "ListIterator"
}
func (it *ListIterator) HasOperation(name string) bool {
//yes := name == expr.NextName || name == expr.ResetName || name == expr.IndexName || name == expr.CountName || name == expr.CurrentName
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName}, name)
return yes
}
func (it *ListIterator) CallOperation(name string, args map[string]any) (v any, err error) {
switch name {
case kern.NextName:
v, err = it.Next()
case kern.ResetName:
err = it.Reset()
case kern.CleanName:
err = it.Clean()
case kern.IndexName:
v = int64(it.Index())
case kern.CurrentName:
v, err = it.Current()
case kern.CountName:
v = it.count
default:
err = kern.ErrNoOperation(name)
}
return
}
func (it *ListIterator) Current() (item any, err error) {
a := *(it.a)
if it.start <= it.stop {
if it.stop < len(a) && it.index >= it.start && it.index <= it.stop {
item = a[it.index]
} else {
err = io.EOF
}
} else {
if it.start < len(a) && it.index >= it.stop && it.index <= it.start {
item = a[it.index]
} else {
err = io.EOF
}
}
return
}
func (it *ListIterator) Next() (item any, err error) {
it.index += it.step
if item, err = it.Current(); err != io.EOF {
it.count++
}
return
}
func (it *ListIterator) Index() int {
return it.index
}
func (it *ListIterator) Count() int {
return it.count
}
func (it *ListIterator) Reset() error {
it.index = it.start - it.step
it.count = 0
return nil
}
func (it *ListIterator) Clean() error {
return nil
}