[m-rev.] For review: Java implementation of IO library
Fergus Henderson
fjh at cs.mu.OZ.AU
Wed Jan 14 15:35:06 AEDT 2004
On 14-Jan-2004, James Goddard <goddardjames at yahoo.com> wrote:
> Index: io.m
> @@ -4615,6 +4818,332 @@
> }
> ").
>
> +:- pragma foreign_code("Java",
> +"
> + // stdin, stdout, stderr and all text files are run through stream
> + // readers/writers, which use the default charset encoding. In other
> + // words, while strings and characters are stored internally using
> + // unicode, all files are read and written using the default system
> + // charset.
> + // Binary files are opened via RandomAccessFile, which supports seek,
> + // but not character encoding/decoding or buffering.
> +
> + public static class MR_MercuryFileStruct {
> + public static int ML_next_stream_id = 0;
> + public int id;
> +
> + public int line_number;
> +
> + public static final int INPUT = 0;
> + public static final int OUTPUT = 1;
> + private int mode;
> +
> + private static final int SEEK_SET = 0;
> + private static final int SEEK_CUR = 1;
> + private static final int SEEK_END = 2;
> +
> + private java.util.Stack pushback = null;
> + private java.io.InputStreamReader input = null;
> + private java.io.OutputStreamWriter output = null;
> + private java.io.RandomAccessFile randomaccess = null;
> +
> + private java.lang.String filename = null;
> +
> + public MR_MercuryFileStruct(java.io.InputStream stream) {
> + line_number = 1;
> + id = ML_next_stream_id++;
> + mode = INPUT;
> + pushback = new java.util.Stack();
> + input = new java.io.InputStreamReader(
> + stream);
> + }
> +
> + public MR_MercuryFileStruct(java.io.OutputStream stream) {
> + line_number = 1;
> + id = ML_next_stream_id++;
> + mode = OUTPUT;
> + output = new java.io.OutputStreamWriter(
> + stream);
> + }
> +
> + public MR_MercuryFileStruct(java.lang.String file, char mode) {
> + line_number = 1;
> + id = ML_next_stream_id++;
> + filename = file;
> + String openstring;
> + if (mode == 'r') {
> + openstring = ""r"";
> + this.mode = INPUT;
> + pushback = new java.util.Stack();
> + } else if (mode == 'r' || mode == 'a') {
> + openstring = ""rw"";
s/'r'/'w'/
This change obviously needs more testing ;-)
> + public int size() {
> + try {
> + return (int) randomaccess.length();
> + } catch (java.lang.Exception e) {
> + return -1;
> + }
> + }
Please document that this function only works for binary files.
(For text files, randomaccess will be null.)
> + public void seek(int flag, int offset) {
> + if (randomaccess == null) {
> + throw new java.lang.RuntimeException(
> + ""Stream not seekable"");
> + // this applies to stdin, stdout and stderr
> + }
The comment here should be updated -- it applies to any text files,
doesn't it?
> + public int getOffset() {
Please document that this function only works for binary files.
> + /* read_char():
> + ** Reads one character in using the default charset
> + ** decoding. Returns -1 at end of file.
> + */
The "/*" should be on a line of its own.
/*
** read_char():
** ...
*/
Also, s/Reads one character/Reads one character from a text input file/
> + /* read_char():
> + ** Reads one byte in from a binary file.
> + ** Returns -1 at end of file.
> + */
> + public int read_byte() {
Likewise. Also s/read_char/read_byte/
> + public void ungetc(int c) {
> + if (mode == OUTPUT) {
> + throw new java.lang.RuntimeException(
> + ""Attempted to unget char to output stream"");
> + }
> + if (c == '\\n') {
> + line_number--;
> + }
> +
> + pushback.push(new Integer(c));
> + }
It's still not clear whether the parameter `c' here is supposed to represent
a character or a byte. Please document this.
If the idea is that it can be used for pushing back either bytes
or characters, depending on whether the stream is a text stream or
a binary stream, then please document that. But I don't know how
that would work with io__write_binary and io__read_binary.
> + public void putc(int c) {
Likewise here.
> + public void close() {
> + try {
> + if (input != null) {
> + input.close();
> + } else if (output != null) {
> + output.close();
> + } else {
> + randomaccess.close();
> + }
I suggest deleting the elses here, so that this code will still work if
more than one of input/output/randomaccess is non-null.
> + // StreamPipe is a mechanism for connecting streams to those of a
> + // Runtime.exec() Process.
> +
> + private static class StreamPipe extends java.lang.Thread {
> + MR_MercuryFileStruct in;
> + MR_MercuryFileStruct out;
> + boolean live = true;
> + boolean closeOutput = false;
> + java.lang.Exception exception = null;
> +
> + StreamPipe(java.io.InputStream in, MR_MercuryFileStruct out) {
> + this.in = new MR_MercuryFileStruct(in);
> + this.out = out;
> + }
> +
> + StreamPipe(MR_MercuryFileStruct in, java.io.OutputStream out) {
> + this.in = in;
> + this.out = new MR_MercuryFileStruct(out);
> + closeOutput = true;
> + }
> +
> + public void run() {
> + try {
> + while (live) {
> + int b = in.read_char();
> + if (b == -1) {
> + break;
> + }
> + out.putc(b);
> + }
> + out.flush();
> + if (closeOutput) {
> + out.close();
> + }
> + }
> + catch (java.lang.Exception e) {
> + exception = e;
> + }
> + }
> + } // class StreamPipe
> +").
It looks like "live" is never set to anything but "true".
> +:- pragma foreign_code("Java",
> +"
> +static MR_MercuryFileStruct mercury_stdin =
> + new MR_MercuryFileStruct(java.lang.System.in);
> +static MR_MercuryFileStruct mercury_stdout =
> + new MR_MercuryFileStruct(java.lang.System.out);
> +static MR_MercuryFileStruct mercury_stderr =
> + new MR_MercuryFileStruct(java.lang.System.err);
> +static MR_MercuryFileStruct mercury_stdin_binary =
> + new MR_MercuryFileStruct(java.lang.System.in);
> +static MR_MercuryFileStruct mercury_stdout_binary =
> + new MR_MercuryFileStruct(java.lang.System.out);
Here there seems to be no distinction between mercury_stdin and
mercury_stdin_binary.
mercury_stdin_binary and mercury_stdout_binary should be opened in
binary mode; in particular, it should be possible to read/write
binary data (bytes), and also to seek on them.
> +static java.lang.Exception MR_io_exception;
Please add a comment "XXX not thread-safe!".
> +:- pragma foreign_proc("Java",
> + io__write_bytes(Message::in, _IO0::di, _IO::uo),
> + [may_call_mercury, promise_pure, thread_safe, tabled_for_io],
> +"{
> + mercury_current_binary_output.write(Message);
> +}").
It would probably be better for write_bytes in Java to behave the
same way it does in .NET. See the long comment in the C# version
of mercury_print_binary_string().
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list