161 lines
3.1 KiB
Go
161 lines
3.1 KiB
Go
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
// All rights reserved.
|
|
|
|
// list-iterator.go
|
|
package expr
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
type ListIterator struct {
|
|
a *ListType
|
|
count int
|
|
index int
|
|
start int
|
|
stop int
|
|
step int
|
|
}
|
|
|
|
func NewListIterator(list *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 := ToGoInt(args[0], "start index"); err == nil {
|
|
if i < 0 {
|
|
i = listLen + i
|
|
}
|
|
it.start = i
|
|
}
|
|
if argc >= 2 {
|
|
if i, err := ToGoInt(args[1], "stop index"); err == nil {
|
|
if i < 0 {
|
|
i = listLen + i
|
|
}
|
|
it.stop = i
|
|
}
|
|
if argc >= 3 {
|
|
if i, err := 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: (*ListType)(&array), count: 0, index: -1, start: 0, stop: len(array) - 1, step: 1}
|
|
return
|
|
}
|
|
|
|
func NewAnyIterator(value any) (it *ListIterator) {
|
|
if value == nil {
|
|
it = NewArrayIterator([]any{})
|
|
} else if list, ok := value.(*ListType); ok {
|
|
it = NewListIterator(list, nil)
|
|
} else if array, ok := value.([]any); ok {
|
|
it = NewArrayIterator(array)
|
|
} else if it1, ok := value.(*ListIterator); ok {
|
|
it = it1
|
|
} else {
|
|
it = NewArrayIterator([]any{value})
|
|
}
|
|
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 == NextName || name == ResetName || name == IndexName || name == CountName || name == CurrentName
|
|
return yes
|
|
}
|
|
|
|
func (it *ListIterator) CallOperation(name string, args map[string]any) (v any, err error) {
|
|
switch name {
|
|
case NextName:
|
|
v, err = it.Next()
|
|
case ResetName:
|
|
err = it.Reset()
|
|
case CleanName:
|
|
err = it.Clean()
|
|
case IndexName:
|
|
v = int64(it.Index())
|
|
case CurrentName:
|
|
v, err = it.Current()
|
|
case CountName:
|
|
v = it.count
|
|
default:
|
|
err = 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
|
|
}
|