Iterator defined by data-source now only requires one method: next()

This commit is contained in:
2024-07-21 05:45:22 +02:00
parent 6ecbe2feb1
commit c461fd138e
3 changed files with 62 additions and 69 deletions
+45 -56
View File
@@ -13,19 +13,29 @@ type dataCursor struct {
ds map[string]Functor
ctx ExprContext
index int
current any
lastErr error
resource any
nextFunc Functor
cleanFunc Functor
resetFunc Functor
currentFunc Functor
// currentFunc Functor
}
func NewDataCursor(ctx ExprContext, ds map[string]Functor) (dc *dataCursor) {
func NewDataCursor(ctx ExprContext, ds map[string]Functor, resource any) (dc *dataCursor) {
dc = &dataCursor{
ds: ds,
index: -1,
ctx: ctx.Clone(),
ds: ds,
index: -1,
current: nil,
lastErr: nil,
resource: resource,
ctx: ctx.Clone(),
nextFunc: ds[NextName],
// currentFunc: ds[CurrentName],
cleanFunc: ds[CleanName],
resetFunc: ds[ResetName],
}
dc.Next()
return
}
@@ -101,6 +111,7 @@ func (dc *dataCursor) Reset() (success bool, err error) {
dc.index = -1
}
exportObjects(dc.ctx, ctx)
dc.Next()
} else {
err = errInvalidDataSource()
}
@@ -129,93 +140,71 @@ func (dc *dataCursor) Clean() (success bool, err error) {
}
func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
ctx := cloneContext(dc.ctx)
if item, err = dc.currentFunc.Invoke(ctx, CurrentName, []any{}); err == nil && item == nil {
if dc.current != nil {
item = dc.current
} else {
err = io.EOF
}
exportObjects(dc.ctx, ctx)
return
}
// func (dc *dataCursor) _Next() (item any, err error) { // must return io.EOF after the last item
// if dc.resource != nil {
// ctx := cloneContext(dc.ctx)
// // fmt.Printf("Entering Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
// if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{dc.resource}); err == nil {
// if item == nil {
// err = io.EOF
// } else {
// dc.index++
// }
// }
// // fmt.Printf("Exiting Inner-Ctx [%p]: %s\n", ctx, CtxToString(ctx, 0))
// exportObjects(dc.ctx, ctx)
// // fmt.Printf("Outer-Ctx [%p]: %s\n", dc.ctx, CtxToString(dc.ctx, 0))
// } else {
// err = errInvalidDataSource()
// }
// return
// }
// func (dc *dataCursor) _filter(item any) (filterdItem any, err error) {
// if filter, ok := dc.ds[filterName]; ok {
// ctx := cloneContext(dc.ctx)
// filterdItem, err = filter.Invoke(ctx, filterName, []any{item, dc.index})
// } else {
// filterdItem = item
// }
// return
// }
func (dc *dataCursor) checkFilter(filter Functor, item any) (accepted bool, err error) {
var v any
var ok bool
ctx := cloneContext(dc.ctx)
if v, err = filter.Invoke(ctx, FilterName, []any{item, dc.index}); err == nil && v != nil {
if accepted, ok = v.(bool); !ok {
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
}
accepted = true // NOTE: A non-boolean value that is not nil means the item has been accepted
}
}
return
}
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
ctx := cloneContext(dc.ctx)
mappedItem, err = mapper.Invoke(ctx, MapName, []any{item, dc.index});
return
}
func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
func (dc *dataCursor) mapItem(mapper Functor, item any) (mappedItem any, err error) {
ctx := cloneContext(dc.ctx)
mappedItem, err = mapper.Invoke(ctx, MapName, []any{item, dc.index})
return
}
func (dc *dataCursor) Next() (current any, err error) { // must return io.EOF after the last item
var accepted bool
if err = dc.lastErr; err != nil {
return
}
current = dc.current
if dc.resource != nil {
filter := dc.ds[FilterName]
mapper := dc.ds[MapName]
for item == nil && err == nil {
var item any
for item == nil && dc.lastErr == nil {
ctx := cloneContext(dc.ctx)
if item, err = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource}); err == nil {
dc.index++
if item, dc.lastErr = dc.nextFunc.Invoke(ctx, NextName, []any{dc.resource, dc.index}); dc.lastErr == nil {
if item == nil {
err = io.EOF
dc.lastErr = io.EOF
} else {
dc.index++
if filter != nil {
if accepted, err = dc.checkFilter(filter, item); err != nil || !accepted {
if accepted, dc.lastErr = dc.checkFilter(filter, item); dc.lastErr != nil || !accepted {
item = nil
}
}
if item != nil && mapper != nil {
item, err = dc.mapItem(mapper, item)
item, dc.lastErr = dc.mapItem(mapper, item)
}
}
}
exportObjects(dc.ctx, ctx)
}
dc.current = item
if dc.lastErr != nil {
dc.Clean()
}
} else {
err = errInvalidDataSource()
dc.lastErr = errInvalidDataSource()
}
return
}
func (dc *dataCursor) Index() int {
return dc.index
return dc.index-1
}