summaryrefslogtreecommitdiff
path: root/libjava/java/io/PipedReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/io/PipedReader.java')
-rw-r--r--libjava/java/io/PipedReader.java210
1 files changed, 210 insertions, 0 deletions
diff --git a/libjava/java/io/PipedReader.java b/libjava/java/io/PipedReader.java
new file mode 100644
index 00000000000..f54c4f8031f
--- /dev/null
+++ b/libjava/java/io/PipedReader.java
@@ -0,0 +1,210 @@
+// PipedReader.java - Piped character stream.
+
+/* Copyright (C) 1998, 1999 Cygnus Solutions
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+package java.io;
+
+/**
+ * @author Tom Tromey <tromey@cygnus.com>
+ * @date September 25, 1998
+ */
+
+/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
+ * "The Java Language Specification", ISBN 0-201-63451-1
+ * Status: Complete to 1.1.
+ */
+
+public class PipedReader extends Reader
+{
+ public void close () throws IOException
+ {
+ closed = true;
+ }
+
+ public void connect (PipedWriter src) throws IOException
+ {
+ if (closed)
+ throw new IOException ("already closed");
+ if (writer != null)
+ {
+ if (writer == src)
+ return;
+ throw new IOException ("already connected");
+ }
+ try
+ {
+ writer = src;
+ writer.connect(this);
+ }
+ catch (IOException e)
+ {
+ writer = null;
+ throw e;
+ }
+ }
+
+ public PipedReader ()
+ {
+ super ();
+ writer = null;
+ closed = false;
+ in = -1;
+ out = 0;
+ pipeBuffer = new char[1024];
+ }
+
+ public PipedReader (PipedWriter src) throws IOException
+ {
+ super ();
+ closed = false;
+ in = -1;
+ out = 0;
+ pipeBuffer = new char[1024];
+ connect (src);
+ }
+
+ public int read (char buf[], int offset, int count) throws IOException
+ {
+ if (closed)
+ throw new IOException ("closed");
+ if (count < 0)
+ throw new ArrayIndexOutOfBoundsException ();
+ int toCopy = count;
+ synchronized (lock)
+ {
+ while (toCopy > 0)
+ {
+ // Wait for data in the pipe. If the writer is closed and
+ // no data has been copied into the output buffer, return
+ // the magic EOF number.
+ while (in == -1)
+ {
+ if (writer.isClosed())
+ {
+ if (toCopy < count)
+ return count - toCopy;
+ return -1;
+ }
+
+ // Note that JCL doesn't say this is the right thing
+ // to do. Still, it feels right, and we must deal
+ // with an interrupt somehow.
+ try
+ {
+ lock.wait();
+ }
+ catch (InterruptedException e)
+ {
+ InterruptedIOException io
+ = new InterruptedIOException (e.getMessage());
+ io.bytesTransferred = count - toCopy;
+ throw io;
+ }
+ }
+ // Now copy some data from pipe into user buffer.
+ int len;
+ if (in < out)
+ len = pipeBuffer.length - out;
+ else
+ len = in - out;
+ len = len > toCopy ? toCopy : len;
+ System.arraycopy(pipeBuffer, out, buf, offset, len);
+ out += len;
+ if (out == pipeBuffer.length)
+ out = 0;
+ toCopy -= len;
+ offset += len;
+ // If we've read all the data, then reset so that we know
+ // there is nothing left to be read.
+ if (in == out)
+ in = -1;
+ // Tell anybody waiting for space in the buffer.
+ lock.notifyAll();
+ }
+ }
+ return count;
+ }
+
+ void receive (char buf[], int offset, int count) throws IOException
+ {
+ if (count < 0)
+ throw new ArrayIndexOutOfBoundsException ();
+ int original = count;
+ synchronized (lock)
+ {
+ while (count > 0)
+ {
+ // Wait until there is some space in the buffer.
+ while (in == out)
+ {
+ try
+ {
+ lock.wait();
+ }
+ catch (InterruptedException e)
+ {
+ // Turn interrupts into IO interrupts.
+ InterruptedIOException io
+ = new InterruptedIOException (e.getMessage());
+ io.bytesTransferred = original - count;
+ throw io;
+ }
+ }
+
+ // Compute destination in the pipe.
+ int base, len;
+ if (in == -1)
+ {
+ base = 0;
+ len = pipeBuffer.length;
+ }
+ else if (in < out)
+ {
+ base = in;
+ len = out - in;
+ }
+ else
+ {
+ base = in;
+ len = pipeBuffer.length - in;
+ }
+ int copyLen = len > count ? count : len;
+ // Copy data and update local state.
+ System.arraycopy(buf, offset, pipeBuffer, base, copyLen);
+ in = base + copyLen;
+ if (in == pipeBuffer.length)
+ in = 0;
+ count -= copyLen;
+ offset += copyLen;
+ // Tell anybody waiting for data.
+ lock.notifyAll();
+ }
+ }
+ }
+
+
+ boolean isClosed ()
+ {
+ return closed;
+ }
+
+ // The associated writer.
+ private PipedWriter writer;
+ // True if this reader has been closed.
+ boolean closed;
+
+ // Index of next character to overwrite when receive() is called.
+ // If -1, then that means the buffer is empty.
+ private int in;
+ // Index of next character to return from read().
+ private int out;
+
+ // The pipe buffer itself.
+ private char[] pipeBuffer;
+}