From ad3c1e5a605dbcdf2f120210782903a100f9cba9 Mon Sep 17 00:00:00 2001 From: Celestino Amoroso Date: Mon, 9 Sep 2024 15:23:07 +0200 Subject: [PATCH] enhanced and simplified Reset(), Clean() and Next() methods --- data-cursor.go | 213 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 139 insertions(+), 74 deletions(-) diff --git a/data-cursor.go b/data-cursor.go index 1c473d7..7ed8687 100644 --- a/data-cursor.go +++ b/data-cursor.go @@ -6,12 +6,14 @@ package expr import ( "io" + "slices" ) type dataCursor struct { ds map[string]Functor ctx ExprContext - initState bool // true if no item has prodiced yet (this replace di initial Next() call in the contructor) + initState bool // true if no item has produced yet (this replace di initial Next() call in the contructor) + // cursorValid bool // true if resource is nil or if clean has not yet been called index int count int current any @@ -26,6 +28,7 @@ func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *da dc = &dataCursor{ ds: ds, initState: true, + // cursorValid: true, index: -1, count: 0, current: nil, @@ -36,7 +39,6 @@ func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *da cleanFunc: ds[CleanName], resetFunc: ds[ResetName], } - //dc.Next() return } @@ -77,7 +79,7 @@ func (dc *dataCursor) String() string { } func (dc *dataCursor) HasOperation(name string) (exists bool) { - exists = name == IndexName + exists = slices.Contains([]string{CleanName, ResetName, CurrentName, IndexName}, name) if !exists { f, ok := dc.ds[name] exists = ok && isFunctor(f) @@ -88,63 +90,83 @@ func (dc *dataCursor) HasOperation(name string) (exists bool) { func (dc *dataCursor) CallOperation(name string, args map[string]any) (value any, err error) { if name == IndexName { value = int64(dc.Index()) + } else if name == CleanName { + err = dc.Clean() + } else if name == ResetName { + err = dc.Reset() } else if functor, ok := dc.ds[name]; ok && isFunctor(functor) { - if functor == dc.cleanFunc { - value, err = dc.Clean() - } else if functor == dc.resetFunc { - value, err = dc.Reset() - } else { - ctx := cloneContext(dc.ctx) - value, err = functor.InvokeNamed(ctx, name, args) - exportObjects(dc.ctx, ctx) - } + ctx := cloneContext(dc.ctx) + value, err = functor.InvokeNamed(ctx, name, args) + exportObjects(dc.ctx, ctx) } else { err = errNoOperation(name) } return } -func (dc *dataCursor) Reset() (success bool, err error) { +// func (dc *dataCursor) Reset() (err error) { +// if dc.resetFunc != nil { +// if dc.resource != nil { +// ctx := cloneContext(dc.ctx) +// actualParams := bindActualParams(dc.resetFunc, []any{dc.resource}) +// _, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams) +// exportObjects(dc.ctx, ctx) +// dc.index = -1 +// dc.count = 0 +// dc.initState = true +// dc.current = nil +// dc.lastErr = nil +// } else { +// err = errInvalidDataSource() +// } +// } else { +// err = errNoOperation(ResetName) +// } +// return +// } + +func (dc *dataCursor) Reset() (err error) { if dc.resetFunc != nil { - if dc.resource != nil { - ctx := cloneContext(dc.ctx) - actualParams := bindActualParams(dc.resetFunc, []any{dc.resource}) - _, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams) - exportObjects(dc.ctx, ctx) - dc.index = -1 - dc.count = 0 - dc.initState = true - dc.current = nil - dc.lastErr = nil - //dc.Next() - } else { - err = errInvalidDataSource() - } - } else { - err = errNoOperation(ResetName) + ctx := cloneContext(dc.ctx) + actualParams := bindActualParams(dc.resetFunc, []any{dc.resource}) + _, err = dc.resetFunc.InvokeNamed(ctx, ResetName, actualParams) + exportObjects(dc.ctx, ctx) } - success = err == nil + dc.index = -1 + dc.count = 0 + dc.initState = true + dc.current = nil + dc.lastErr = nil return } -func (dc *dataCursor) Clean() (success bool, err error) { +func (dc *dataCursor) Clean() (err error) { if dc.cleanFunc != nil { - if dc.resource != nil { - ctx := cloneContext(dc.ctx) - actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource}) - _, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams) - // dc.resource = nil - exportObjects(dc.ctx, ctx) - } else { - err = errInvalidDataSource() - } - } else { - err = errNoOperation(CleanName) + ctx := cloneContext(dc.ctx) + actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource}) + _, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams) + exportObjects(dc.ctx, ctx) } - success = err == nil + dc.lastErr = io.EOF return } +// func (dc *dataCursor) Clean() (err error) { +// if dc.cleanFunc != nil { +// if dc.resource != nil { +// ctx := cloneContext(dc.ctx) +// actualParams := bindActualParams(dc.cleanFunc, []any{dc.resource}) +// _, err = dc.cleanFunc.InvokeNamed(ctx, CleanName, actualParams) +// exportObjects(dc.ctx, ctx) +// } else { +// err = errInvalidDataSource() +// } +// } else { +// err = errNoOperation(CleanName) +// } +// return +// } + func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item dc.init() @@ -191,46 +213,89 @@ func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF af return } current = dc.current - if dc.resource != nil { - filter := dc.ds[FilterName] - mapper := dc.ds[MapName] - var item any - for item == nil && dc.lastErr == nil { - ctx := cloneContext(dc.ctx) - dc.index++ + filter := dc.ds[FilterName] + mapper := dc.ds[MapName] + var item any + for item == nil && dc.lastErr == nil { + ctx := cloneContext(dc.ctx) + dc.index++ - actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index}) - if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil { - if item == nil { - dc.lastErr = io.EOF - } else { - accepted := true - if filter != nil { - if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted { - item = nil - } - } - if accepted { - dc.count++ - } - if item != nil && mapper != nil { - item, dc.lastErr = dc.mapItem(mapper, item) + actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index}) + if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil { + if item == nil { + dc.lastErr = io.EOF + } else { + accepted := true + if filter != nil { + if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted { + item = nil } } + if accepted { + dc.count++ + } + if item != nil && mapper != nil { + item, dc.lastErr = dc.mapItem(mapper, item) + } } - exportObjects(dc.ctx, ctx) } - dc.current = item - if dc.lastErr != nil { - dc.index-- - dc.Clean() - } - } else { - dc.lastErr = errInvalidDataSource() + exportObjects(dc.ctx, ctx) + } + dc.current = item + if dc.lastErr != nil { + dc.index-- + dc.Clean() } return } +// func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item +// if dc.initState { +// dc.init() +// } else if err = dc.lastErr; err != nil { +// return +// } +// current = dc.current +// if dc.resource != nil { +// filter := dc.ds[FilterName] +// mapper := dc.ds[MapName] +// var item any +// for item == nil && dc.lastErr == nil { +// ctx := cloneContext(dc.ctx) +// dc.index++ + +// actualParams := bindActualParams(dc.nextFunc, []any{dc.resource, dc.index}) +// if item, dc.lastErr = dc.nextFunc.InvokeNamed(ctx, NextName, actualParams); dc.lastErr == nil { +// if item == nil { +// dc.lastErr = io.EOF +// } else { +// accepted := true +// if filter != nil { +// if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted { +// item = nil +// } +// } +// if accepted { +// dc.count++ +// } +// if item != nil && mapper != nil { +// item, dc.lastErr = dc.mapItem(mapper, item) +// } +// } +// } +// exportObjects(dc.ctx, ctx) +// } +// dc.current = item +// if dc.lastErr != nil { +// dc.index-- +// dc.Clean() +// } +// } else { +// dc.lastErr = errInvalidDataSource() +// } +// return +// } + func (dc *dataCursor) Index() int { return dc.index - 1 }