diff options
Diffstat (limited to 'libjava/java/io/PipedReader.java')
-rw-r--r-- | libjava/java/io/PipedReader.java | 210 |
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; +} |