Fixed issue: #55

This commit is contained in:
UnlegitDqrk
2026-03-02 15:49:57 +01:00
parent 139af3f28b
commit 67429a7a31
10 changed files with 170 additions and 14 deletions

View File

@@ -81,6 +81,10 @@ public class IoLib extends TwoArgFunction {
abstract public void write( LuaString string ) throws IOException;
abstract public void flush() throws IOException;
abstract public boolean isstdfile();
/**
* Close the underlying resource explicitly.
* Callers must not rely on garbage collection or finalization for cleanup.
*/
abstract public void close() throws IOException;
abstract public boolean isclosed();
// returns new position
@@ -118,18 +122,6 @@ public class IoLib extends TwoArgFunction {
public String tojstring() {
return "file: " + Integer.toHexString(hashCode());
}
public void finalize() throws Throwable {
try {
if (!isclosed()) {
try {
close();
} catch (IOException ignore) {}
}
} finally {
super.finalize();
}
}
}
/** Enumerated value representing stdin */
@@ -222,12 +214,15 @@ public class IoLib extends TwoArgFunction {
private static final int IO_INDEX = 18;
private static final int LINES_ITER = 19;
private static final int IO_LINESX = 20;
private static final int FILE_LINESX = 21;
public static final String[] IO_NAMES = {
"close",
"flush",
"input",
"lines",
"linesx",
"open",
"output",
"popen",
@@ -241,6 +236,7 @@ public class IoLib extends TwoArgFunction {
"close",
"flush",
"lines",
"linesx",
"read",
"seek",
"setvbuf",
@@ -316,6 +312,7 @@ public class IoLib extends TwoArgFunction {
case IO_POPEN: return iolib._io_popen(args.checkjstring(1),args.optjstring(2,"r"));
case IO_OPEN: return iolib._io_open(args.checkjstring(1), args.optjstring(2,"r"));
case IO_LINES: return iolib._io_lines(args);
case IO_LINESX: return iolib._io_linesx(args);
case IO_READ: return iolib._io_read(args);
case IO_WRITE: return iolib._io_write(args);
@@ -323,6 +320,7 @@ public class IoLib extends TwoArgFunction {
case FILE_FLUSH: return iolib._file_flush(args.arg1());
case FILE_SETVBUF: return iolib._file_setvbuf(args.arg1(),args.checkjstring(2),args.optint(3,8192));
case FILE_LINES: return iolib._file_lines(args);
case FILE_LINESX: return iolib._file_linesx(args);
case FILE_READ: return iolib._file_read(args.arg1(),args.subargs(2));
case FILE_SEEK: return iolib._file_seek(args.arg1(),args.optjstring(2,"cur"),args.optint(3,0));
case FILE_WRITE: return iolib._file_write(args.arg1(),args.subargs(2));
@@ -332,6 +330,12 @@ public class IoLib extends TwoArgFunction {
}
} catch ( IOException ioe ) {
if (opcode == LINES_ITER) {
if (toclose && f != null && !f.isclosed()) {
try {
f.close();
} catch (IOException ignore) {
}
}
String s = ioe.getMessage();
error(s != null ? s : ioe.toString());
}
@@ -407,6 +411,14 @@ public class IoLib extends TwoArgFunction {
return lines(infile, filename != null, args.subargs(2));
}
// io.linesx(filename, ...) -> closable iterator
public Varargs _io_linesx(Varargs args) {
String filename = args.optjstring(1, null);
File infile = filename==null? input(): ioopenfile(FTYPE_NAMED, filename,"r");
checkopen(infile);
return linesx(infile, filename != null, args.subargs(2));
}
// io.read(...) -> (...)
public Varargs _io_read(Varargs args) throws IOException {
checkopen(input());
@@ -447,6 +459,11 @@ public class IoLib extends TwoArgFunction {
return lines(checkfile(args.arg1()), false, args.subargs(2));
}
// file:linesx(...) -> closable iterator
public Varargs _file_linesx(Varargs args) {
return linesx(checkfile(args.arg1()), false, args.subargs(2));
}
// file:read(...) -> (...)
public Varargs _file_read(LuaValue file, Varargs subargs) throws IOException {
return ioread(checkfile(file),subargs);
@@ -481,7 +498,7 @@ public class IoLib extends TwoArgFunction {
if ( f == null ) argerror(1, "not a file: " + file);
if ( f.isclosed() ) error("file is already closed");
Varargs ret = ioread(f, args);
if (toclose && ret.isnil(1) && f.eof()) f.close();
if (toclose && ret.isnil(1) && !f.isclosed()) f.close();
return ret;
}
@@ -532,6 +549,84 @@ public class IoLib extends TwoArgFunction {
}
}
private Varargs linesx(final File f, boolean toclose, Varargs args) {
try {
return new LinesIterator(f, toclose, args);
} catch ( Exception e ) {
return error("linesx: "+e);
}
}
private final class LinesIterator extends LuaTable {
private final File file;
private final boolean toclose;
private final Varargs args;
private boolean closed;
LinesIterator(File file, boolean toclose, Varargs args) {
this.file = file;
this.toclose = toclose;
this.args = args.dealias();
set("next", new next());
set("close", new close());
LuaTable mt = new LuaTable();
mt.set(CALL, new invoke());
setmetatable(mt);
}
private Varargs nextLine() {
if (closed || file.isclosed()) {
return NIL;
}
try {
Varargs ret = ioread(file, args);
if (toclose && ret.isnil(1) && !file.isclosed()) {
file.close();
closed = true;
}
return ret;
} catch (IOException ioe) {
if (!file.isclosed()) {
try {
file.close();
} catch (IOException ignore) {
}
}
closed = true;
String s = ioe.getMessage();
error(s != null ? s : ioe.toString());
return NONE;
}
}
private final class invoke extends VarArgFunction {
public Varargs invoke(Varargs args) {
return nextLine();
}
}
private final class next extends VarArgFunction {
public Varargs invoke(Varargs args) {
return nextLine();
}
}
private final class close extends OneArgFunction {
public LuaValue call(LuaValue self) {
if (!closed && !file.isclosed()) {
try {
file.close();
} catch (IOException ioe) {
String s = ioe.getMessage();
error(s != null ? s : ioe.toString());
}
}
closed = true;
return TRUE;
}
}
}
private static Varargs iowrite(File f, Varargs args) throws IOException {
for ( int i=1, n=args.narg(); i<=n; i++ )
f.write( args.checkstring(i) );
@@ -685,4 +780,4 @@ public class IoLib extends TwoArgFunction {
}
}