// 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 int64 index int64 start int64 stop int64 step int64 } func NewListIterator(list *kern.ListType, args []any) (it *ListIterator) { var argc int = 0 listLen := int64(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.ToGoInt64(args[0], "start index"); err == nil { if i < 0 { i = listLen + i } it.start = i } if argc >= 2 { if i, err := kern.ToGoInt64(args[1], "stop index"); err == nil { if i < 0 { i = listLen + i } it.stop = i } if argc >= 3 { if i, err := kern.ToGoInt64(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: int64(len(array)) - 1, step: 1} return } func (it *ListIterator) String() string { var l = int64(0) if it.a != nil { l = int64(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 < int64(len(a)) && it.index >= it.start && it.index <= it.stop { item = a[it.index] } else { err = io.EOF } } else { if it.start < int64(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() int64 { return it.index } func (it *ListIterator) Count() int64 { 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 }