diff --git a/func-os.go b/func-os.go new file mode 100644 index 0000000..f81443e --- /dev/null +++ b/func-os.go @@ -0,0 +1,164 @@ +// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). +// All rights reserved. + +// func-os.go +package expr + +import ( + "bufio" + "fmt" + "io" + "os" +) + +type osHandle interface { + getFile() *os.File +} + +type osWriter struct { + fh *os.File + writer *bufio.Writer +} + +func (h *osWriter) getFile() *os.File { + return h.fh +} + +type osReader struct { + fh *os.File + reader *bufio.Reader +} + +func (h *osReader) getFile() *os.File { + return h.fh +} + +func createFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { + var filePath string + if len(args) > 0 { + filePath, _ = args[0].(string) + } + + if len(filePath) > 0 { + var fh *os.File + if fh, err = os.Create(filePath); err == nil { + result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)} + } + } else { + err = fmt.Errorf("%s(): missing the file path", name) + } + return +} + +func openFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { + var filePath string + if len(args) > 0 { + filePath, _ = args[0].(string) + } + + if len(filePath) > 0 { + var fh *os.File + if fh, err = os.Open(filePath); err == nil { + result = &osReader{fh: fh, reader: bufio.NewReader(fh)} + } + } else { + err = fmt.Errorf("%s(): missing the file path", name) + } + return +} + +func appendFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { + var filePath string + if len(args) > 0 { + filePath, _ = args[0].(string) + } + + if len(filePath) > 0 { + var fh *os.File + if fh, err = os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0660); err == nil { + result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)} + } + } else { + err = fmt.Errorf("%s(): missing the file path", name) + } + return +} + +func closeFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { + var handle osHandle + + if len(args) > 0 { + handle, _ = args[0].(osHandle) + } + + if handle != nil { + if fh := handle.getFile(); fh != nil { + if w, ok := handle.(*osWriter); ok { + err = w.writer.Flush() + } + if err == nil { + err = fh.Close() + } + } + } else { + err = fmt.Errorf("%s(): invalid file handle", name) + } + result = err == nil + return +} + +func writeFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { + var handle osHandle + + if len(args) > 0 { + handle, _ = args[0].(osHandle) + } + + if handle != nil { + if fh := handle.getFile(); fh != nil { + if w, ok := handle.(*osWriter); ok { + result, err = fmt.Fprint(w.writer, args[1:]...) + } + } + } + return +} + +func readFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { + var handle osHandle + + if len(args) > 0 { + handle, _ = args[0].(osHandle) + } + + if handle != nil { + if fh := handle.getFile(); fh != nil { + if r, ok := handle.(*osReader); ok { + var limit byte = '\n' + var v string + if len(args) > 1 { + if s, ok := args[1].(string); ok && len(s) > 0 { + limit = s[0] + } + } + if v, err = r.reader.ReadString(limit); err == nil || err == io.EOF { + if len(v) > 0 && v[len(v)-1] == limit { + result = v[0 : len(v)-1] + } else { + result = v + } + } + } + } + } + return +} + +func ImportOsFuncs(ctx ExprContext) { + ctx.RegisterFunc("openFile", &simpleFunctor{f: openFileFunc}, 1, 1) + ctx.RegisterFunc("appendFile", &simpleFunctor{f: appendFileFunc}, 1, 1) + ctx.RegisterFunc("createFile", &simpleFunctor{f: createFileFunc}, 1, 1) + ctx.RegisterFunc("writeFile", &simpleFunctor{f: writeFileFunc}, 1, -1) + ctx.RegisterFunc("readFile", &simpleFunctor{f: readFileFunc}, 1, 2) + ctx.RegisterFunc("closeFile", &simpleFunctor{f: closeFileFunc}, 1, 1) +}