data-cursor.go: the inizialization of the current item is done in the Next() method.

This allows the application of the filter and map operator to the first item too.
This commit is contained in:
Celestino Amoroso 2024-07-23 05:46:37 +02:00
parent dfae593e86
commit 315f5b22d3

View File

@ -5,13 +5,13 @@
package expr package expr
import ( import (
"errors"
"io" "io"
) )
type dataCursor struct { type dataCursor struct {
ds map[string]Functor ds map[string]Functor
ctx ExprContext ctx ExprContext
initState bool // true if no item has prodiced yet (this replace di initial Next() call in the contructor)
index int index int
count int count int
current any current any
@ -24,18 +24,19 @@ type dataCursor struct {
func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *dataCursor) { func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *dataCursor) {
dc = &dataCursor{ dc = &dataCursor{
ds: ds, ds: ds,
index: -1, initState: true,
count: 0, index: -1,
current: nil, count: 0,
lastErr: nil, current: nil,
resource: resource, lastErr: nil,
ctx: ctx.Clone(), resource: resource,
nextFunc: ds[NextName], ctx: ctx.Clone(),
nextFunc: ds[NextName],
cleanFunc: ds[CleanName], cleanFunc: ds[CleanName],
resetFunc: ds[ResetName], resetFunc: ds[ResetName],
} }
dc.Next() //dc.Next()
return return
} }
@ -107,12 +108,14 @@ func (dc *dataCursor) Reset() (success bool, err error) {
if dc.resetFunc != nil { if dc.resetFunc != nil {
if dc.resource != nil { if dc.resource != nil {
ctx := cloneContext(dc.ctx) ctx := cloneContext(dc.ctx)
if _, err = dc.resetFunc.Invoke(ctx, ResetName, []any{dc.resource}); err == nil { _, err = dc.resetFunc.Invoke(ctx, ResetName, []any{dc.resource})
dc.index = -1
dc.count = 0
}
exportObjects(dc.ctx, ctx) exportObjects(dc.ctx, ctx)
dc.Next() dc.index = -1
dc.count = 0
dc.initState = true
dc.current = nil
dc.lastErr = nil
//dc.Next()
} else { } else {
err = errInvalidDataSource() err = errInvalidDataSource()
} }
@ -128,19 +131,21 @@ func (dc *dataCursor) Clean() (success bool, err error) {
if dc.resource != nil { if dc.resource != nil {
ctx := cloneContext(dc.ctx) ctx := cloneContext(dc.ctx)
_, err = dc.cleanFunc.Invoke(ctx, CleanName, []any{dc.resource}) _, err = dc.cleanFunc.Invoke(ctx, CleanName, []any{dc.resource})
dc.resource = nil // dc.resource = nil
exportObjects(dc.ctx, ctx) exportObjects(dc.ctx, ctx)
} else { } else {
err = errInvalidDataSource() err = errInvalidDataSource()
} }
} else { } else {
err = errors.New("no 'clean' function defined in the data-source") err = errNoOperation(CleanName)
} }
success = err == nil success = err == nil
return return
} }
func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
dc.init()
if dc.current != nil { if dc.current != nil {
item = dc.current item = dc.current
} else { } else {
@ -167,8 +172,17 @@ func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err err
return return
} }
func (dc *dataCursor) init() {
if dc.initState {
dc.initState = false
dc.Next()
}
}
func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item
if err = dc.lastErr; err != nil { if dc.initState {
dc.init()
} else if err = dc.lastErr; err != nil {
return return
} }
current = dc.current current = dc.current
@ -214,7 +228,6 @@ func (dc *dataCursor) Index() int {
return dc.index - 1 return dc.index - 1
} }
func (dc *dataCursor) Count() int { func (dc *dataCursor) Count() int {
return dc.count return dc.count
} }