[m-rev.] For review: Java implementation of IO library
James Goddard
goddardjames at yahoo.com
Thu Jan 15 17:46:57 AEDT 2004
> I think it would be possible to use reflection to do it correctly for
> Java 1.4, by extracting the FileChannel for System.out and System.in,
> and invoking seek on that. If you use Reflection for everything, the
> code for it should compile fine in Java < 1.4. This code is a bit
> implementation-dependent, but if it doesn't work it will just throw
> an exception.
Ok, here's my next attempt. I've copied your get_output_channel()
function in and altered it to make get_input_channel() as well.
seek(), size() and getOffset() all use Reflection to access those
FileChannels now.
It's all getting so ugly!! =(
diff -u io.m io.m
--- io.m 15 Jan 2004 01:49:26 -0000
+++ io.m 15 Jan 2004 06:38:28 -0000
@@ -4851,7 +4851,9 @@
private java.io.BufferedInputStream binary_input = null;
/* binary_stdout only */
private java.io.BufferedOutputStream binary_output = null;
+
int position = 0;
+ private java.lang.Object channel = null;
/*
** This constructor is for text input streams.
@@ -4900,49 +4902,36 @@
}
}
- /*
- ** This constructor is only used for mercury_stdin_binary. It
- ** opens stdin as an approximation of a binary file and allows
- ** a limited amount of seeking.
- */
public MR_MercuryFileStruct(java.io.InputStream stream,
boolean openAsBinary)
{
+ id = ML_next_stream_id++;
+ mode = INPUT;
+ pushback = new java.util.Stack();
+
if (!openAsBinary) {
- id = ML_next_stream_id++;
- mode = INPUT;
- pushback = new java.util.Stack();
input = new java.io.
InputStreamReader(stream);
} else {
- id = ML_next_stream_id++;
- mode = INPUT;
- pushback = new java.util.Stack();
-
binary_input = new java.io.BufferedInputStream(
stream);
+ channel = get_in_channel();
}
}
- /*
- ** This constructor is only used for mercury_stdout_binary. It
- ** opens stdout as an approximation of a binary file and allows
- ** a limited amount of seeking.
- */
public MR_MercuryFileStruct(java.io.OutputStream stream,
boolean openAsBinary)
{
+ id = ML_next_stream_id++;
+ mode = OUTPUT;
+
if (!openAsBinary) {
- id = ML_next_stream_id++;
- mode = OUTPUT;
output = new java.io.
OutputStreamWriter(stream);
} else {
- id = ML_next_stream_id++;
- mode = OUTPUT;
-
binary_output = new java.io.
BufferedOutputStream(stream);
+ channel = get_out_channel();
}
}
@@ -4950,7 +4939,8 @@
** size():
** Returns the length of a binary file. XXX Note that this
** method will return -1 for mercury_stdin_binary and
- ** the current position for mercury_stdout_binary.
+ ** the current position for mercury_stdout_binary in Java
+ ** versions < 1.4.
*/
public int size() {
if (randomaccess != null) {
@@ -4959,10 +4949,20 @@
} catch (java.io.IOException e) {
return -1;
}
- } else if (binary_output != null) {
- return position;
- } else {
- return -1;
+ }
+
+ try {
+ java.lang.reflect.Method size_mth =
+ channel.getClass().
+ getMethod(""size"", null);
+ return ((Long) size_mth.invoke(channel, null)).
+ intValue();
+ } catch (java.lang.Exception e) {
+ if (binary_output != null) {
+ return position;
+ } else {
+ return -1;
+ }
}
}
@@ -4971,11 +4971,21 @@
** seek relative to start, current position or end
** depending on the flag.
** This function only works for binary files.
- ** XXX Note that for mercury_stdin_binary, seek may be
+ ** The binary versions of stdin and stdout are treated
+ ** specially. For java version 1.4, Reflection is used to
+ ** obtain and use the neccessary FileChannel object needed
+ ** to perform seeking on each.
+ ** For older versions, seeking is rather limited.
+ ** For mercury_stdin_binary, seek may be
** only be done forwards from the current position and for
** mercury_stdout_binary seek is not supported at all.
*/
public void seek(int flag, int offset) {
+ if (channel != null) {
+ channelSeek(flag, offset);
+ return;
+ }
+
if (input != null || output != null) {
throw new java.lang.RuntimeException(
""text streams are not "" +
@@ -4996,6 +5006,8 @@
}
pushback = new java.util.Stack();
+ line_number = 1;
+
try {
switch (flag) {
case SEEK_SET:
@@ -5027,6 +5039,42 @@
}
}
+ private void channelSeek(int flag, int offset) {
+ pushback = new java.util.Stack();
+ line_number = 1;
+
+ try {
+ switch (flag) {
+ case SEEK_SET:
+ position = offset;
+ break;
+ case SEEK_CUR:
+ position = getOffset() +
+ offset;
+ break;
+ case SEEK_END:
+ position = size() + offset;
+ break;
+ default:
+ throw new java.lang.
+ RuntimeException(
+ ""Invalid seek flag"");
+ }
+
+ Class[] argTypes = {Long.TYPE};
+ java.lang.reflect.Method seek_mth =
+ channel.getClass().getMethod(
+ ""position"", argTypes);
+
+ Object[] args = {new Long(position)};
+ seek_mth.invoke(channel, args);
+ }
+ catch (java.lang.Exception e) {
+ throw new java.lang.RuntimeException(
+ e.getMessage());
+ }
+ }
+
/*
** getOffset():
** Returns the current position in a binary file.
@@ -5039,12 +5087,22 @@
} catch (java.io.IOException e) {
return -1;
}
- } else if (binary_input != null ||
- binary_output != null)
- {
- return position;
- } else {
- return -1;
+ }
+
+ try {
+ java.lang.reflect.Method posn_mth =
+ channel.getClass().
+ getMethod(""position"", null);
+ return ((Long) posn_mth.invoke(channel, null)).
+ intValue();
+ } catch (java.lang.Exception e) {
+ if (binary_input != null ||
+ binary_output != null)
+ {
+ return position;
+ } else {
+ return -1;
+ }
}
}
@@ -5287,6 +5345,97 @@
}
}
} // class StreamPipe
+
+ /*
+ ** get_out_channel():
+ ** Uses reflection to retrieve the FileChannel for System.out on
+ ** platforms supporting Java v1.4
+ */
+ static java.lang.Object/*FileChannel*/ get_out_channel() {
+ try {
+ java.lang.Object/*PrintStream*/ ps =
+ java.lang.System.out;
+
+ // Simulate
+ // BufferedOutputStream bos =
+ // (BufferedOutputStream) ps.out;
+ // using reflection.
+ java.lang.reflect.Field out_fld =
+ ps.getClass().getSuperclass().
+ getDeclaredField(""out"");
+ out_fld.setAccessible(true);
+ java.lang.Object/*BufferedOutputStream*/ bos =
+ out_fld.get(ps);
+
+ // Simulate
+ // FileOutputStream fs =
+ // (FileOutputStream) bos.out;
+ // using reflection.
+ java.lang.reflect.Field out_fld2 =
+ bos.getClass().getSuperclass().
+ getDeclaredField(""out"");
+ out_fld2.setAccessible(true);
+ java.lang.Object/*FileStream*/ fs = out_fld2.get(bos);
+
+ // Simulate
+ // FileChannel channel = fs.getChannel();
+ // using reflection.
+ java.lang.reflect.Method getChannel_mth =
+ fs.getClass().getMethod(
+ ""getChannel"", null);
+ java.lang.Object/*FileChannel*/ channel =
+ getChannel_mth.invoke(fs, null);
+
+ return channel;
+ } catch (java.lang.Exception e) {
+ return null;
+ }
+ }
+
+ /*
+ ** get_in_channel():
+ ** Uses reflection to retrieve the FileChannel for System.in on
+ ** platforms supporting Java v1.4
+ */
+ static java.lang.Object/*FileChannel*/ get_in_channel() {
+ try {
+ java.lang.Object/*InputStream*/ is = System.in;
+
+ // Simulate
+ // BufferedInputStream bis =
+ // (BufferedInputStream) is.in;
+ // using reflection.
+ java.lang.reflect.Field in_fld =
+ is.getClass().getSuperclass().
+ getDeclaredField(""in"");
+ in_fld.setAccessible(true);
+ java.lang.Object/*BufferedInputStream*/ bis =
+ in_fld.get(is);
+
+ // Simulate
+ // FileInputStream fs =
+ // (FileInputStream) bis.in;
+ // using reflection.
+ java.lang.reflect.Field in_fld2 =
+ bis.getClass().getSuperclass().
+ getDeclaredField(""in"");
+ in_fld2.setAccessible(true);
+ java.lang.Object/*FileStream*/ fs = in_fld2.get(bis);
+
+ // Simulate
+ // FileChannel channel = fs.getChannel();
+ // using reflection.
+ java.lang.reflect.Method getChannel_mth =
+ fs.getClass().getMethod(
+ ""getChannel"", null);
+ java.lang.Object/*FileChannel*/ channel =
+ getChannel_mth.invoke(fs, null);
+
+ return channel;
+ } catch (java.lang.Exception e) {
+ return null;
+ }
+ }
").
:- pragma foreign_code("C", "
--------------------------------------------------------------------------
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