Files
expr/builtin-os-file-iter-line.go
T

144 lines
3.4 KiB
Go

// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// builtin-os-file.go
package expr
import (
"fmt"
"slices"
"git.portale-stac.it/go-pkg/expr/file"
"git.portale-stac.it/go-pkg/expr/kern"
)
const fileLineIteratorType = "fileLineIterator"
type fileFileLineIterator struct {
reader *file.Reader
index int64
count int64
line string
autoClose bool
}
func newFileLineIterator(r *file.Reader, autoClose bool) *fileFileLineIterator {
return &fileFileLineIterator{reader: r, index: -1, autoClose: autoClose}
}
func (it *fileFileLineIterator) TypeName() string {
return fileLineIteratorType
}
func (it *fileFileLineIterator) String() string {
if it.reader != nil && it.reader.GetFile() != nil {
return fmt.Sprintf("$(%s@%q)", fileLineIteratorType, it.reader.GetName())
}
return fmt.Sprintf("$(%s@<nil>)", fileLineIteratorType)
}
func (it *fileFileLineIterator) Count() int64 {
return it.count
}
func (it *fileFileLineIterator) Next() (item any, err error) { // must return io.EOF after the last item
if it.line, err = it.reader.ReadString('\n'); err == nil {
it.index++
it.count++
item = it.line[0 : len(it.line)-1]
} else if it.autoClose {
it.Clean()
}
return
}
func (it *fileFileLineIterator) Current() (item any, err error) {
if len(it.line) > 0 {
item = it.line[0 : len(it.line)-1]
}
return
}
func (it *fileFileLineIterator) Index() int64 {
return it.index
}
func (it *fileFileLineIterator) Reset() (err error) {
if err = it.reader.Reset(); err == nil {
it.index = -1
it.count = 0
it.line = ""
}
return
}
func (it *fileFileLineIterator) HasOperation(name string) bool {
return slices.Contains([]string{kern.NextName, kern.ResetName, kern.IndexName, kern.CountName, kern.CurrentName, kern.CleanName}, name)
}
func (it *fileFileLineIterator) Clean() (err error) {
if it.reader != nil {
if err = it.reader.Close(); err == nil {
it.reader = nil
}
}
return nil
}
func (it *fileFileLineIterator) 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 fileLineIteratorFunc(ctx kern.ExprContext, name string, args map[string]any) (result any, err error) {
var handle *file.Reader
var invalidFileHandle any
var autoClose bool
result = nil
// if handle, ok = args[paramHandleOrPath].(*osReader); !ok {
// if fileName, ok := args[paramHandleOrPath].(string); ok && len(fileName) > 0 {
// var handleAny any
// if handleAny, err = openFileFunc(ctx, name, map[string]any{kern.ParamFilepath: fileName}); err != nil {
// return
// }
// if handleAny != nil {
// handle = handleAny.(*osReader)
// autoClose = true
// }
// } else {
// invalidFileHandle = args[paramHandleOrPath]
// }
// }
// if handle != nil {
// result = newFileLineIterator(handle, autoClose)
// }
if handle, invalidFileHandle, autoClose, err = initFileHandle(ctx, name, args); err == nil {
if handle != nil {
result = newFileLineIterator(handle, autoClose)
}
}
if err == nil && (handle == nil || invalidFileHandle != nil) {
err = errInvalidFileHandle(name, invalidFileHandle)
}
return
}