138 lines
2.7 KiB
Go
138 lines
2.7 KiB
Go
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
// All rights reserved.
|
|
|
|
// int-iterator.go
|
|
package expr
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"slices"
|
|
|
|
"git.portale-stac.it/go-pkg/expr/kern"
|
|
)
|
|
|
|
type IntIterator struct {
|
|
count int64
|
|
index int64
|
|
start int64
|
|
stop int64
|
|
step int64
|
|
}
|
|
|
|
func NewIntIterator(args []any) (it *IntIterator, err error) {
|
|
var argc int = 0
|
|
if args != nil {
|
|
argc = len(args)
|
|
}
|
|
it = &IntIterator{count: 0, index: -1, start: 0, stop: 0, step: 1}
|
|
if argc >= 1 {
|
|
if it.stop, err = kern.ToGoInt64(args[0], "start index"); err != nil {
|
|
return
|
|
}
|
|
if argc >= 2 {
|
|
it.start = it.stop
|
|
if it.stop, err = kern.ToGoInt64(args[1], "stop index"); err != nil {
|
|
return
|
|
}
|
|
if argc >= 3 {
|
|
if it.step, err = kern.ToGoInt64(args[2], "step"); err != nil {
|
|
return
|
|
}
|
|
} else if it.start > it.stop {
|
|
it.step = -1
|
|
}
|
|
}
|
|
}
|
|
if it.step == 0 {
|
|
err = fmt.Errorf("step cannot be zero")
|
|
return
|
|
}
|
|
if it.start < it.stop && it.step < 0 {
|
|
err = fmt.Errorf("step cannot be negative when start < stop")
|
|
return
|
|
}
|
|
if it.start > it.stop && it.step > 0 {
|
|
err = fmt.Errorf("step cannot be positive when start > stop")
|
|
return
|
|
}
|
|
it.Reset()
|
|
return
|
|
}
|
|
|
|
func (it *IntIterator) String() string {
|
|
return fmt.Sprintf("$(%d..%d..%d)", it.start, it.stop, it.step)
|
|
}
|
|
|
|
func (it *IntIterator) TypeName() string {
|
|
return "IntIterator"
|
|
}
|
|
|
|
func (it *IntIterator) HasOperation(name string) bool {
|
|
yes := slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName}, name)
|
|
return yes
|
|
}
|
|
|
|
func (it *IntIterator) 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 *IntIterator) Current() (item any, err error) {
|
|
if it.start <= it.stop {
|
|
if it.index >= it.start && it.index < it.stop {
|
|
item = it.index
|
|
} else {
|
|
err = io.EOF
|
|
}
|
|
} else {
|
|
if it.index > it.stop && it.index <= it.start {
|
|
item = it.index
|
|
} else {
|
|
err = io.EOF
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (it *IntIterator) Next() (item any, err error) {
|
|
it.index += it.step
|
|
if item, err = it.Current(); err != io.EOF {
|
|
it.count++
|
|
}
|
|
return
|
|
}
|
|
|
|
func (it *IntIterator) Index() int64 {
|
|
return it.index
|
|
}
|
|
|
|
func (it *IntIterator) Count() int64 {
|
|
return it.count
|
|
}
|
|
|
|
func (it *IntIterator) Reset() error {
|
|
it.index = it.start - it.step
|
|
it.count = 0
|
|
return nil
|
|
}
|
|
|
|
func (it *IntIterator) Clean() error {
|
|
return nil
|
|
}
|