net.sandius.rembulan.lib.IoLib Maven / Gradle / Ivy
/*
* Copyright 2016 Miroslav Janíček
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* --
* Portions of this file are licensed under the Lua license. For Lua
* licensing details, please visit
*
* http://www.lua.org/license.html
*
* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package net.sandius.rembulan.lib;
import net.sandius.rembulan.Table;
import net.sandius.rembulan.TableFactory;
import net.sandius.rembulan.Userdata;
import net.sandius.rembulan.runtime.LuaFunction;
/**
* The I/O library provides two different styles for file manipulation. The first one uses
* implicit file handles; that is, there are operations to set a default input file and
* a default output file, and all input/output operations are over these default files.
* The second style uses explicit file handles.
*
* When using implicit file handles, all operations are supplied by table {@code io}.
* When using explicit file handles, the operation {@link #_open() {@code io.open}}
* returns a file handle and then all operations are supplied as methods of the file handle.
*
* The table {@code io} also provides three predefined file handles with their usual
* meanings from C: {@code io.stdin}, {@code io.stdout}, and {@code io.stderr}.
* The I/O library never closes these files.
*
* Unless otherwise stated, all I/O functions return nil on failure (plus an error
* message as a second result and a system-dependent error code as a third result) and some
* value different from nil on success. On non-POSIX systems, the computation
* of the error message and error code in case of errors may be not thread safe, because they
* rely on the global C variable {@code errno}.
*/
public abstract class IoLib extends Lib {
@Override
public String name() {
return "io";
}
@Override
public Table toTable(TableFactory tableFactory) {
Table t = tableFactory.newTable();
t.rawset("close", _close());
t.rawset("flush", _flush());
t.rawset("input", _input());
t.rawset("lines", _lines());
t.rawset("open", _open());
t.rawset("output", _output());
t.rawset("popen", _popen());
t.rawset("read", _read());
t.rawset("tmpfile", _tmpfile());
t.rawset("type", _type());
t.rawset("write", _write());
t.rawset("stdin", _stdin());
t.rawset("stdout", _stdout());
t.rawset("stderr", _stderr());
return t;
}
/**
* {@code io.close ([file])}
*
* Equivalent to {@code file:close()}. Without a {@code file}, closes the default
* output file.
*
* @return the {@code io.close} function
*/
public abstract LuaFunction _close();
/**
* {@code io.flush ()}
*
* Equivalent to {@code io.output():flush()}.
*
* @return the {@code io.flush} function
*/
public abstract LuaFunction _flush();
/**
* {@code io.input ([file])}
*
* When called with a file name, it opens the named file (in text mode), and sets
* its handle as the default input file. When called with a file handle, it simply sets
* this file handle as the default input file. When called without parameters, it returns
* the current default input file.
*
* In case of errors this function raises the error, instead of returning an error code.
*
* @return the {@code io.input} function
*/
public abstract LuaFunction _input();
/**
* {@code io.lines ([filename, ···])}
*
* Opens the given file name in read mode and returns an iterator function that works
* like {@code file:lines(···)} over the opened file. When the iterator function detects
* the end of file, it returns no values (to finish the loop) and automatically closes
* the file.
*
* The call {@code io.lines()} (with no file name) is equivalent
* to {@code io.input():lines("*l")}; that is, it iterates over the lines of the default
* input file. In this case it does not close the file when the loop ends.
*
* In case of errors this function raises the error, instead of returning an error code.
*
* @return the {@code io.lines} function
*/
public abstract LuaFunction _lines();
/**
* {@code io.open (filename [, mode])}
*
* This function opens a file, in the mode specified in the string {@code mode}.
* It returns a new file handle, or, in case of errors, nil plus an error message.
*
* The mode string can be any of the following:
*
* - "{@code r}": read mode (the default);
* - "{@code w}": write mode;
* - "{@code a}": append mode;
* - "{@code r+}": update mode, all previous data is preserved;
* - "{@code w+}": update mode, all previous data is erased;
* - "{@code a+}": append update mode, previous data is preserved, writing is only allowed
* at the end of file.
*
*
* The mode string can also have a '{@code b}' at the end, which is needed in some systems
* to open the file in binary mode.
*
* @return the {@code io.open} function
*/
public abstract LuaFunction _open();
/**
* {@code io.output ([file])}
*
* Similar to {@code io.input}, but operates over the default output file.
*
* @return the {@code io.output} function
*/
public abstract LuaFunction _output();
/**
* {@code io.popen (prog [, mode])}
*
* This function is system dependent and is not available on all platforms.
*
* Starts program {@code prog} in a separated process and returns a file handle
* that you can use to read data from this program (if {@code mode} is "{@code r}",
* the default) or to write data to this program (if {@code mode} is "{@code w}").
*
* @return the {@code io.popen} function
*/
public abstract LuaFunction _popen();
/**
* {@code io.read (···)}
*
* Equivalent to {@code io.input():read(···)}.
*
* @return the {@code io.read} function
*/
public abstract LuaFunction _read();
/**
* {@code io.tmpfile ()}
*
* Returns a handle for a temporary file. This file is opened in update mode
* and it is automatically removed when the program ends.
*
* @return the {@code io.tmpfile} function
*/
public abstract LuaFunction _tmpfile();
/**
* {@code io.type (obj)}
*
* Checks whether {@code obj} is a valid file handle. Returns the string {@code "file"}
* if {@code obj} is an open file handle, {@code "closed file"} if {@code obj} is
* a closed file handle, or nil if {@code obj} is not a file handle.
*
* @return the {@code io.type} function
*/
public abstract LuaFunction _type();
/**
* {@code io.write (···)}
*
* Equivalent to {@link #_file_write() {@code io.output():write(···)}}.
*
* @return the {@code io.write} function
*/
public abstract LuaFunction _write();
/**
* {@code io.stdin}
*
* The standard input file.
*
* @return the standard input file
*/
public abstract Userdata _stdin();
/**
* {@code io.stdout}
*
* The standard output file.
*
* @return the standard output file
*/
public abstract Userdata _stdout();
/**
* {@code io.stderr}
*
* The standard error file.
*
* @return the standard error file
*/
public abstract Userdata _stderr();
/**
* {@code file:close ()}
*
* Closes {@code file}. Note that files are automatically closed when their handles
* are garbage collected, but that takes an unpredictable amount of time to happen.
*
* When closing a file handle created with {@link #_popen() {@code io.popen}},
* {@code file:close} returns the same values returned by {@code os.execute}.
*
* @return the {@code file:close} function
*/
public abstract LuaFunction _file_close();
/**
* {@code file:flush ()}
*
* Saves any written data to {@code file}.
*
* @return the {@code file:flush} function
*/
public abstract LuaFunction _file_flush();
/**
* {@code file:lines (···)}
*
* Returns an iterator function that, each time it is called, reads the file according
* to the given formats. When no format is given, uses "{@code l}" as a default.
* As an example, the construction
*
*
* {@code
* for c in file:lines(1) do body end
* }
*
*
* will iterate over all characters of the file, starting at the current position.
* Unlike {@link #_lines() {@code io.lines}}, this function does not close the file
* when the loop ends.
*
* In case of errors this function raises the error, instead of returning an error code.
*
* @return the {@code file:lines} function
*/
public abstract LuaFunction _file_lines();
/**
* {@code file:read (···)}
*
* Reads the file {@code file}, according to the given formats, which specify what to read.
* For each format, the function returns a string or a number with the characters read,
* or nil if it cannot read data with the specified format. (In this latter case,
* the function does not read subsequent formats.) When called without formats, it uses
* a default format that reads the next line (see below).
*
* The available formats are
*
* - "{@code n}": reads a numeral and returns it as a float or an integer,
* following the lexical conventions of Lua. (The numeral may have leading spaces and a sign.)
* This format always reads the longest input sequence that is a valid prefix for a numeral;
* if that prefix does not form a valid numeral (e.g., an empty string, {@code "0x"},
* or {@code "3.4e-"}), it is discarded and the function returns nil.
* - "{@code a}": reads the whole file, starting at the current position. On end of file,
* it returns the empty string.
* - "{@code l}": reads the next line skipping the end of line, returning nil
* on end of file. This is the default format.
* - "{@code L}": reads the next line keeping the end-of-line character (if present),
* returning nil on end of file.
* - number: reads a string with up to this number of bytes,
* returning nil on end of file. If number is zero, it reads nothing
* and returns an empty string, or nil on end of file.
*
*
* The formats "{@code l}" and "{@code L}" should be used only for text files.
*
* @return the {@code file:read} function
*/
public abstract LuaFunction _file_read();
/**
* {@code file:seek ([whence [, offset]])}
*
* Sets and gets the file position, measured from the beginning of the file,
* to the position given by offset plus a base specified by the string {@code whence},
* as follows:
*
* - {@code "set"}: base is position 0 (beginning of the file);
* - {@code "cur"}: base is current position;
* - {@code "end"}: base is end of file;
*
*
* In case of success, {@code seek} returns the final file position, measured in bytes from
* the beginning of the file. If {@code seek} fails, it returns nil, plus a string
* describing the error.
*
* The default value for whence is {@code "cur"}, and for offset is 0. Therefore,
* the call {@code file:seek()} returns the current file position, without changing it;
* the call {@code file:seek("set")} sets the position to the beginning of the file
* (and returns 0); and the call {@code file:seek("end")} sets the position to the end
* of the file, and returns its size.
*
* @return the {@code file:seek} function
*/
public abstract LuaFunction _file_seek();
/**
* {@code file:setvbuf (mode [, size])}
*
* Sets the buffering mode for an output file. There are three available modes:
*
* - {@code "no"}: no buffering; the result of any output operation appears
* immediately.
* - {@code "full"}: full buffering; output operation is performed only when
* the buffer is full or when you explicitly flush the file
* (see {@link #_flush() {@code io.flush}}).
* - {@code "line"}: line buffering; output is buffered until a newline is output
* or there is any input from some special files (such as a terminal device).
*
* For the last two cases, {@code size} specifies the size of the buffer, in bytes.
* The default is an appropriate size.
*
* @return the {@code file:setvbuf} function
*/
public abstract LuaFunction _file_setvbuf();
/**
* {@code file:write (···)}
*
* Writes the value of each of its arguments to {@code file}. The arguments must be strings
* or numbers.
*
* In case of success, this function returns {@code file}. Otherwise it returns nil
* plus a string describing the error.
*
* @return the {@code file:write} function
*/
public abstract LuaFunction _file_write();
}