mirror of
https://github.com/akyaiy/GoSally-mvp.git
synced 2026-01-08 09:32:26 +00:00
Project structure refactor:
- Change package name general_server to gateway - Changing the structure of directories and packages - Adding vendor to the project
This commit is contained in:
749
vendor/github.com/yuin/gopher-lua/iolib.go
generated
vendored
Normal file
749
vendor/github.com/yuin/gopher-lua/iolib.go
generated
vendored
Normal file
@@ -0,0 +1,749 @@
|
||||
package lua
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var ioFuncs = map[string]LGFunction{
|
||||
"close": ioClose,
|
||||
"flush": ioFlush,
|
||||
"lines": ioLines,
|
||||
"input": ioInput,
|
||||
"output": ioOutput,
|
||||
"open": ioOpenFile,
|
||||
"popen": ioPopen,
|
||||
"read": ioRead,
|
||||
"type": ioType,
|
||||
"tmpfile": ioTmpFile,
|
||||
"write": ioWrite,
|
||||
}
|
||||
|
||||
const lFileClass = "FILE*"
|
||||
|
||||
type lFile struct {
|
||||
fp *os.File
|
||||
pp *exec.Cmd
|
||||
writer io.Writer
|
||||
reader *bufio.Reader
|
||||
stdout io.ReadCloser
|
||||
closed bool
|
||||
}
|
||||
|
||||
type lFileType int
|
||||
|
||||
const (
|
||||
lFileFile lFileType = iota
|
||||
lFileProcess
|
||||
)
|
||||
|
||||
const fileDefOutIndex = 1
|
||||
const fileDefInIndex = 2
|
||||
const fileDefaultWriteBuffer = 4096
|
||||
const fileDefaultReadBuffer = 4096
|
||||
|
||||
func checkFile(L *LState) *lFile {
|
||||
ud := L.CheckUserData(1)
|
||||
if file, ok := ud.Value.(*lFile); ok {
|
||||
return file
|
||||
}
|
||||
L.ArgError(1, "file expected")
|
||||
return nil
|
||||
}
|
||||
|
||||
func errorIfFileIsClosed(L *LState, file *lFile) {
|
||||
if file.closed {
|
||||
L.ArgError(1, "file is closed")
|
||||
}
|
||||
}
|
||||
|
||||
func newFile(L *LState, file *os.File, path string, flag int, perm os.FileMode, writable, readable bool) (*LUserData, error) {
|
||||
ud := L.NewUserData()
|
||||
var err error
|
||||
if file == nil {
|
||||
file, err = os.OpenFile(path, flag, perm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
lfile := &lFile{fp: file, pp: nil, writer: nil, reader: nil, stdout: nil, closed: false}
|
||||
ud.Value = lfile
|
||||
if writable {
|
||||
lfile.writer = file
|
||||
}
|
||||
if readable {
|
||||
lfile.reader = bufio.NewReaderSize(file, fileDefaultReadBuffer)
|
||||
}
|
||||
L.SetMetatable(ud, L.GetTypeMetatable(lFileClass))
|
||||
return ud, nil
|
||||
}
|
||||
|
||||
func newProcess(L *LState, cmd string, writable, readable bool) (*LUserData, error) {
|
||||
ud := L.NewUserData()
|
||||
c, args := popenArgs(cmd)
|
||||
pp := exec.Command(c, args...)
|
||||
lfile := &lFile{fp: nil, pp: pp, writer: nil, reader: nil, stdout: nil, closed: false}
|
||||
ud.Value = lfile
|
||||
|
||||
var err error
|
||||
if writable {
|
||||
lfile.writer, err = pp.StdinPipe()
|
||||
}
|
||||
if readable {
|
||||
lfile.stdout, err = pp.StdoutPipe()
|
||||
lfile.reader = bufio.NewReaderSize(lfile.stdout, fileDefaultReadBuffer)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = pp.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
L.SetMetatable(ud, L.GetTypeMetatable(lFileClass))
|
||||
return ud, nil
|
||||
}
|
||||
|
||||
func (file *lFile) Type() lFileType {
|
||||
if file.fp == nil {
|
||||
return lFileProcess
|
||||
}
|
||||
return lFileFile
|
||||
}
|
||||
|
||||
func (file *lFile) Name() string {
|
||||
switch file.Type() {
|
||||
case lFileFile:
|
||||
return fmt.Sprintf("file %s", file.fp.Name())
|
||||
case lFileProcess:
|
||||
return fmt.Sprintf("process %s", file.pp.Path)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (file *lFile) AbandonReadBuffer() error {
|
||||
if file.Type() == lFileFile && file.reader != nil {
|
||||
_, err := file.fp.Seek(-int64(file.reader.Buffered()), 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file.reader = bufio.NewReaderSize(file.fp, fileDefaultReadBuffer)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func fileDefOut(L *LState) *LUserData {
|
||||
return L.Get(UpvalueIndex(1)).(*LTable).RawGetInt(fileDefOutIndex).(*LUserData)
|
||||
}
|
||||
|
||||
func fileDefIn(L *LState) *LUserData {
|
||||
return L.Get(UpvalueIndex(1)).(*LTable).RawGetInt(fileDefInIndex).(*LUserData)
|
||||
}
|
||||
|
||||
func fileIsWritable(L *LState, file *lFile) int {
|
||||
if file.writer == nil {
|
||||
L.Push(LNil)
|
||||
L.Push(LString(fmt.Sprintf("%s is opened for only reading.", file.Name())))
|
||||
L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack
|
||||
return 3
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func fileIsReadable(L *LState, file *lFile) int {
|
||||
if file.reader == nil {
|
||||
L.Push(LNil)
|
||||
L.Push(LString(fmt.Sprintf("%s is opened for only writing.", file.Name())))
|
||||
L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack
|
||||
return 3
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var stdFiles = []struct {
|
||||
name string
|
||||
file *os.File
|
||||
writable bool
|
||||
readable bool
|
||||
}{
|
||||
{"stdout", os.Stdout, true, false},
|
||||
{"stdin", os.Stdin, false, true},
|
||||
{"stderr", os.Stderr, true, false},
|
||||
}
|
||||
|
||||
func OpenIo(L *LState) int {
|
||||
mod := L.RegisterModule(IoLibName, map[string]LGFunction{}).(*LTable)
|
||||
mt := L.NewTypeMetatable(lFileClass)
|
||||
mt.RawSetString("__index", mt)
|
||||
L.SetFuncs(mt, fileMethods)
|
||||
mt.RawSetString("lines", L.NewClosure(fileLines, L.NewFunction(fileLinesIter)))
|
||||
|
||||
for _, finfo := range stdFiles {
|
||||
file, _ := newFile(L, finfo.file, "", 0, os.FileMode(0), finfo.writable, finfo.readable)
|
||||
mod.RawSetString(finfo.name, file)
|
||||
}
|
||||
uv := L.CreateTable(2, 0)
|
||||
uv.RawSetInt(fileDefOutIndex, mod.RawGetString("stdout"))
|
||||
uv.RawSetInt(fileDefInIndex, mod.RawGetString("stdin"))
|
||||
for name, fn := range ioFuncs {
|
||||
mod.RawSetString(name, L.NewClosure(fn, uv))
|
||||
}
|
||||
mod.RawSetString("lines", L.NewClosure(ioLines, uv, L.NewClosure(ioLinesIter, uv)))
|
||||
// Modifications are being made in-place rather than returned?
|
||||
L.Push(mod)
|
||||
return 1
|
||||
}
|
||||
|
||||
var fileMethods = map[string]LGFunction{
|
||||
"__tostring": fileToString,
|
||||
"write": fileWrite,
|
||||
"close": fileClose,
|
||||
"flush": fileFlush,
|
||||
"lines": fileLines,
|
||||
"read": fileRead,
|
||||
"seek": fileSeek,
|
||||
"setvbuf": fileSetVBuf,
|
||||
}
|
||||
|
||||
func fileToString(L *LState) int {
|
||||
file := checkFile(L)
|
||||
if file.Type() == lFileFile {
|
||||
if file.closed {
|
||||
L.Push(LString("file (closed)"))
|
||||
} else {
|
||||
L.Push(LString("file"))
|
||||
}
|
||||
} else {
|
||||
if file.closed {
|
||||
L.Push(LString("process (closed)"))
|
||||
} else {
|
||||
L.Push(LString("process"))
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func fileWriteAux(L *LState, file *lFile, idx int) int {
|
||||
if n := fileIsWritable(L, file); n != 0 {
|
||||
return n
|
||||
}
|
||||
errorIfFileIsClosed(L, file)
|
||||
top := L.GetTop()
|
||||
out := file.writer
|
||||
var err error
|
||||
for i := idx; i <= top; i++ {
|
||||
L.CheckTypes(i, LTNumber, LTString)
|
||||
s := LVAsString(L.Get(i))
|
||||
if _, err = out.Write(unsafeFastStringToReadOnlyBytes(s)); err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
}
|
||||
|
||||
file.AbandonReadBuffer()
|
||||
L.Push(LTrue)
|
||||
return 1
|
||||
errreturn:
|
||||
|
||||
file.AbandonReadBuffer()
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack
|
||||
return 3
|
||||
}
|
||||
|
||||
func fileCloseAux(L *LState, file *lFile) int {
|
||||
file.closed = true
|
||||
var err error
|
||||
if file.writer != nil {
|
||||
if bwriter, ok := file.writer.(*bufio.Writer); ok {
|
||||
if err = bwriter.Flush(); err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
}
|
||||
}
|
||||
file.AbandonReadBuffer()
|
||||
|
||||
switch file.Type() {
|
||||
case lFileFile:
|
||||
if err = file.fp.Close(); err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
L.Push(LTrue)
|
||||
return 1
|
||||
case lFileProcess:
|
||||
if file.stdout != nil {
|
||||
file.stdout.Close() // ignore errors
|
||||
}
|
||||
err = file.pp.Wait()
|
||||
var exitStatus int // Initialised to zero value = 0
|
||||
if err != nil {
|
||||
if e2, ok := err.(*exec.ExitError); ok {
|
||||
if s, ok := e2.Sys().(syscall.WaitStatus); ok {
|
||||
exitStatus = s.ExitStatus()
|
||||
} else {
|
||||
err = errors.New("Unimplemented for system where exec.ExitError.Sys() is not syscall.WaitStatus.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
exitStatus = 0
|
||||
}
|
||||
L.Push(LNumber(exitStatus))
|
||||
return 1
|
||||
}
|
||||
|
||||
errreturn:
|
||||
L.RaiseError(err.Error())
|
||||
return 0
|
||||
}
|
||||
|
||||
func fileFlushAux(L *LState, file *lFile) int {
|
||||
if n := fileIsWritable(L, file); n != 0 {
|
||||
return n
|
||||
}
|
||||
errorIfFileIsClosed(L, file)
|
||||
|
||||
if bwriter, ok := file.writer.(*bufio.Writer); ok {
|
||||
if err := bwriter.Flush(); err != nil {
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
return 2
|
||||
}
|
||||
}
|
||||
L.Push(LTrue)
|
||||
return 1
|
||||
}
|
||||
|
||||
func fileReadAux(L *LState, file *lFile, idx int) int {
|
||||
if n := fileIsReadable(L, file); n != 0 {
|
||||
return n
|
||||
}
|
||||
errorIfFileIsClosed(L, file)
|
||||
if L.GetTop() == idx-1 {
|
||||
L.Push(LString("*l"))
|
||||
}
|
||||
var err error
|
||||
top := L.GetTop()
|
||||
for i := idx; i <= top; i++ {
|
||||
switch lv := L.Get(i).(type) {
|
||||
case LNumber:
|
||||
size := int64(lv)
|
||||
if size == 0 {
|
||||
_, err = file.reader.ReadByte()
|
||||
if err == io.EOF {
|
||||
L.Push(LNil)
|
||||
goto normalreturn
|
||||
}
|
||||
file.reader.UnreadByte()
|
||||
}
|
||||
var buf []byte
|
||||
var iseof bool
|
||||
buf, err, iseof = readBufioSize(file.reader, size)
|
||||
if iseof {
|
||||
L.Push(LNil)
|
||||
goto normalreturn
|
||||
}
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
L.Push(LString(string(buf)))
|
||||
case LString:
|
||||
options := L.CheckString(i)
|
||||
if len(options) > 0 && options[0] != '*' {
|
||||
L.ArgError(2, "invalid options:"+options)
|
||||
}
|
||||
for _, opt := range options[1:] {
|
||||
switch opt {
|
||||
case 'n':
|
||||
var v LNumber
|
||||
_, err = fmt.Fscanf(file.reader, LNumberScanFormat, &v)
|
||||
if err == io.EOF {
|
||||
L.Push(LNil)
|
||||
goto normalreturn
|
||||
}
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
L.Push(v)
|
||||
case 'a':
|
||||
var buf []byte
|
||||
buf, err = ioutil.ReadAll(file.reader)
|
||||
if err == io.EOF {
|
||||
L.Push(emptyLString)
|
||||
goto normalreturn
|
||||
}
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
L.Push(LString(string(buf)))
|
||||
case 'l':
|
||||
var buf []byte
|
||||
var iseof bool
|
||||
buf, err, iseof = readBufioLine(file.reader)
|
||||
if iseof {
|
||||
L.Push(LNil)
|
||||
goto normalreturn
|
||||
}
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
L.Push(LString(string(buf)))
|
||||
default:
|
||||
L.ArgError(2, "invalid options:"+string(opt))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
normalreturn:
|
||||
return L.GetTop() - top
|
||||
|
||||
errreturn:
|
||||
L.RaiseError(err.Error())
|
||||
//L.Push(LNil)
|
||||
//L.Push(LString(err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var fileSeekOptions = []string{"set", "cur", "end"}
|
||||
|
||||
func fileSeek(L *LState) int {
|
||||
file := checkFile(L)
|
||||
if file.Type() != lFileFile {
|
||||
L.Push(LNil)
|
||||
L.Push(LString("can not seek a process."))
|
||||
return 2
|
||||
}
|
||||
|
||||
top := L.GetTop()
|
||||
if top == 1 {
|
||||
L.Push(LString("cur"))
|
||||
L.Push(LNumber(0))
|
||||
} else if top == 2 {
|
||||
L.Push(LNumber(0))
|
||||
}
|
||||
|
||||
var pos int64
|
||||
var err error
|
||||
|
||||
err = file.AbandonReadBuffer()
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
|
||||
pos, err = file.fp.Seek(L.CheckInt64(3), L.CheckOption(2, fileSeekOptions))
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
|
||||
L.Push(LNumber(pos))
|
||||
return 1
|
||||
|
||||
errreturn:
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
func fileWrite(L *LState) int {
|
||||
return fileWriteAux(L, checkFile(L), 2)
|
||||
}
|
||||
|
||||
func fileClose(L *LState) int {
|
||||
return fileCloseAux(L, checkFile(L))
|
||||
}
|
||||
|
||||
func fileFlush(L *LState) int {
|
||||
return fileFlushAux(L, checkFile(L))
|
||||
}
|
||||
|
||||
func fileLinesIter(L *LState) int {
|
||||
var file *lFile
|
||||
if ud, ok := L.Get(1).(*LUserData); ok {
|
||||
file = ud.Value.(*lFile)
|
||||
} else {
|
||||
file = L.Get(UpvalueIndex(2)).(*LUserData).Value.(*lFile)
|
||||
}
|
||||
buf, _, err := file.reader.ReadLine()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
L.Push(LNil)
|
||||
return 1
|
||||
}
|
||||
L.RaiseError(err.Error())
|
||||
}
|
||||
L.Push(LString(string(buf)))
|
||||
return 1
|
||||
}
|
||||
|
||||
func fileLines(L *LState) int {
|
||||
file := checkFile(L)
|
||||
ud := L.CheckUserData(1)
|
||||
if n := fileIsReadable(L, file); n != 0 {
|
||||
return 0
|
||||
}
|
||||
L.Push(L.NewClosure(fileLinesIter, L.Get(UpvalueIndex(1)), ud))
|
||||
return 1
|
||||
}
|
||||
|
||||
func fileRead(L *LState) int {
|
||||
return fileReadAux(L, checkFile(L), 2)
|
||||
}
|
||||
|
||||
var filebufOptions = []string{"no", "full"}
|
||||
|
||||
func fileSetVBuf(L *LState) int {
|
||||
var err error
|
||||
var writer io.Writer
|
||||
file := checkFile(L)
|
||||
if n := fileIsWritable(L, file); n != 0 {
|
||||
return n
|
||||
}
|
||||
switch filebufOptions[L.CheckOption(2, filebufOptions)] {
|
||||
case "no":
|
||||
switch file.Type() {
|
||||
case lFileFile:
|
||||
file.writer = file.fp
|
||||
case lFileProcess:
|
||||
file.writer, err = file.pp.StdinPipe()
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
}
|
||||
case "full", "line": // TODO line buffer not supported
|
||||
bufsize := L.OptInt(3, fileDefaultWriteBuffer)
|
||||
switch file.Type() {
|
||||
case lFileFile:
|
||||
file.writer = bufio.NewWriterSize(file.fp, bufsize)
|
||||
case lFileProcess:
|
||||
writer, err = file.pp.StdinPipe()
|
||||
if err != nil {
|
||||
goto errreturn
|
||||
}
|
||||
file.writer = bufio.NewWriterSize(writer, bufsize)
|
||||
}
|
||||
}
|
||||
L.Push(LTrue)
|
||||
return 1
|
||||
errreturn:
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
func ioInput(L *LState) int {
|
||||
if L.GetTop() == 0 {
|
||||
L.Push(fileDefIn(L))
|
||||
return 1
|
||||
}
|
||||
switch lv := L.Get(1).(type) {
|
||||
case LString:
|
||||
file, err := newFile(L, nil, string(lv), os.O_RDONLY, 0600, false, true)
|
||||
if err != nil {
|
||||
L.RaiseError(err.Error())
|
||||
}
|
||||
L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefInIndex, file)
|
||||
L.Push(file)
|
||||
return 1
|
||||
case *LUserData:
|
||||
if _, ok := lv.Value.(*lFile); ok {
|
||||
L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefInIndex, lv)
|
||||
L.Push(lv)
|
||||
return 1
|
||||
}
|
||||
|
||||
}
|
||||
L.ArgError(1, "string or file expedted, but got "+L.Get(1).Type().String())
|
||||
return 0
|
||||
}
|
||||
|
||||
func ioClose(L *LState) int {
|
||||
if L.GetTop() == 0 {
|
||||
return fileCloseAux(L, fileDefOut(L).Value.(*lFile))
|
||||
}
|
||||
return fileClose(L)
|
||||
}
|
||||
|
||||
func ioFlush(L *LState) int {
|
||||
return fileFlushAux(L, fileDefOut(L).Value.(*lFile))
|
||||
}
|
||||
|
||||
func ioLinesIter(L *LState) int {
|
||||
var file *lFile
|
||||
toclose := false
|
||||
if ud, ok := L.Get(1).(*LUserData); ok {
|
||||
file = ud.Value.(*lFile)
|
||||
} else {
|
||||
file = L.Get(UpvalueIndex(2)).(*LUserData).Value.(*lFile)
|
||||
toclose = true
|
||||
}
|
||||
buf, _, err := file.reader.ReadLine()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if toclose {
|
||||
fileCloseAux(L, file)
|
||||
}
|
||||
L.Push(LNil)
|
||||
return 1
|
||||
}
|
||||
L.RaiseError(err.Error())
|
||||
}
|
||||
L.Push(LString(string(buf)))
|
||||
return 1
|
||||
}
|
||||
|
||||
func ioLines(L *LState) int {
|
||||
if L.GetTop() == 0 {
|
||||
L.Push(L.Get(UpvalueIndex(2)))
|
||||
L.Push(fileDefIn(L))
|
||||
return 2
|
||||
}
|
||||
|
||||
path := L.CheckString(1)
|
||||
ud, err := newFile(L, nil, path, os.O_RDONLY, os.FileMode(0600), false, true)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
L.Push(L.NewClosure(ioLinesIter, L.Get(UpvalueIndex(1)), ud))
|
||||
return 1
|
||||
}
|
||||
|
||||
var ioOpenOpions = []string{"r", "rb", "w", "wb", "a", "ab", "r+", "rb+", "w+", "wb+", "a+", "ab+"}
|
||||
|
||||
func ioOpenFile(L *LState) int {
|
||||
path := L.CheckString(1)
|
||||
if L.GetTop() == 1 {
|
||||
L.Push(LString("r"))
|
||||
}
|
||||
mode := os.O_RDONLY
|
||||
perm := 0600
|
||||
writable := true
|
||||
readable := true
|
||||
switch ioOpenOpions[L.CheckOption(2, ioOpenOpions)] {
|
||||
case "r", "rb":
|
||||
mode = os.O_RDONLY
|
||||
writable = false
|
||||
case "w", "wb":
|
||||
mode = os.O_WRONLY | os.O_TRUNC | os.O_CREATE
|
||||
readable = false
|
||||
case "a", "ab":
|
||||
mode = os.O_WRONLY | os.O_APPEND | os.O_CREATE
|
||||
case "r+", "rb+":
|
||||
mode = os.O_RDWR
|
||||
case "w+", "wb+":
|
||||
mode = os.O_RDWR | os.O_TRUNC | os.O_CREATE
|
||||
case "a+", "ab+":
|
||||
mode = os.O_APPEND | os.O_RDWR | os.O_CREATE
|
||||
}
|
||||
file, err := newFile(L, nil, path, mode, os.FileMode(perm), writable, readable)
|
||||
if err != nil {
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
L.Push(LNumber(1)) // C-Lua compatibility: Original Lua pushes errno to the stack
|
||||
return 3
|
||||
}
|
||||
L.Push(file)
|
||||
return 1
|
||||
|
||||
}
|
||||
|
||||
var ioPopenOptions = []string{"r", "w"}
|
||||
|
||||
func ioPopen(L *LState) int {
|
||||
cmd := L.CheckString(1)
|
||||
if L.GetTop() == 1 {
|
||||
L.Push(LString("r"))
|
||||
} else if L.GetTop() > 1 && (L.Get(2)).Type() == LTNil {
|
||||
L.SetTop(1)
|
||||
L.Push(LString("r"))
|
||||
}
|
||||
var file *LUserData
|
||||
var err error
|
||||
|
||||
switch ioPopenOptions[L.CheckOption(2, ioPopenOptions)] {
|
||||
case "r":
|
||||
file, err = newProcess(L, cmd, false, true)
|
||||
case "w":
|
||||
file, err = newProcess(L, cmd, true, false)
|
||||
}
|
||||
if err != nil {
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
return 2
|
||||
}
|
||||
L.Push(file)
|
||||
return 1
|
||||
}
|
||||
|
||||
func ioRead(L *LState) int {
|
||||
return fileReadAux(L, fileDefIn(L).Value.(*lFile), 1)
|
||||
}
|
||||
|
||||
func ioType(L *LState) int {
|
||||
ud, udok := L.Get(1).(*LUserData)
|
||||
if !udok {
|
||||
L.Push(LNil)
|
||||
return 1
|
||||
}
|
||||
file, ok := ud.Value.(*lFile)
|
||||
if !ok {
|
||||
L.Push(LNil)
|
||||
return 1
|
||||
}
|
||||
if file.closed {
|
||||
L.Push(LString("closed file"))
|
||||
return 1
|
||||
}
|
||||
L.Push(LString("file"))
|
||||
return 1
|
||||
}
|
||||
|
||||
func ioTmpFile(L *LState) int {
|
||||
file, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
L.Push(LNil)
|
||||
L.Push(LString(err.Error()))
|
||||
return 2
|
||||
}
|
||||
L.G.tempFiles = append(L.G.tempFiles, file)
|
||||
ud, _ := newFile(L, file, "", 0, os.FileMode(0), true, true)
|
||||
L.Push(ud)
|
||||
return 1
|
||||
}
|
||||
|
||||
func ioOutput(L *LState) int {
|
||||
if L.GetTop() == 0 {
|
||||
L.Push(fileDefOut(L))
|
||||
return 1
|
||||
}
|
||||
switch lv := L.Get(1).(type) {
|
||||
case LString:
|
||||
file, err := newFile(L, nil, string(lv), os.O_WRONLY|os.O_CREATE, 0600, true, false)
|
||||
if err != nil {
|
||||
L.RaiseError(err.Error())
|
||||
}
|
||||
L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefOutIndex, file)
|
||||
L.Push(file)
|
||||
return 1
|
||||
case *LUserData:
|
||||
if _, ok := lv.Value.(*lFile); ok {
|
||||
L.Get(UpvalueIndex(1)).(*LTable).RawSetInt(fileDefOutIndex, lv)
|
||||
L.Push(lv)
|
||||
return 1
|
||||
}
|
||||
|
||||
}
|
||||
L.ArgError(1, "string or file expedted, but got "+L.Get(1).Type().String())
|
||||
return 0
|
||||
}
|
||||
|
||||
func ioWrite(L *LState) int {
|
||||
return fileWriteAux(L, fileDefOut(L).Value.(*lFile), 1)
|
||||
}
|
||||
|
||||
//
|
||||
Reference in New Issue
Block a user