diff options
author | Tom Tromey <tromey@redhat.com> | 2006-05-01 22:41:20 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2006-05-01 22:41:20 +0000 |
commit | 6e6ab68e1fbb18d190529b9d942bfb96bbeed6aa (patch) | |
tree | 3601ac72ee333a27b069ff1f9e9fdf98550b6ee8 | |
parent | 331cb4f500d051fcca71396900ad28e591eebd0b (diff) | |
download | classpath-6e6ab68e1fbb18d190529b9d942bfb96bbeed6aa.tar.gz |
* java/nio/ByteBufferImpl.java (compact): Don't reset position
in empty case.
* gnu/java/nio/ChannelReader.java (read): Synchronize.
(close): Synchronize.
* java/nio/ShortBufferImpl.java (compact): Rewrote.
* java/nio/LongBufferImpl.java (compact): Rewrote.
* java/nio/IntBufferImpl.java (compact): Rewrote.
* java/nio/FloatBufferImpl.java (compact): Rewrote.
* java/nio/DoubleBufferImpl.java (compact): Rewrote.
* java/nio/CharBufferImpl.java (compact): Rewrote.
* gnu/java/nio/ChannelWriter.java: New file.
* java/nio/channels/Channels.java (newWriter): Implemented.
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | gnu/java/nio/ChannelReader.java | 206 | ||||
-rw-r--r-- | gnu/java/nio/ChannelWriter.java | 190 | ||||
-rw-r--r-- | java/nio/ByteBufferImpl.java | 7 | ||||
-rw-r--r-- | java/nio/CharBufferImpl.java | 13 | ||||
-rw-r--r-- | java/nio/DoubleBufferImpl.java | 13 | ||||
-rw-r--r-- | java/nio/FloatBufferImpl.java | 13 | ||||
-rw-r--r-- | java/nio/IntBufferImpl.java | 13 | ||||
-rw-r--r-- | java/nio/LongBufferImpl.java | 13 | ||||
-rw-r--r-- | java/nio/ShortBufferImpl.java | 13 | ||||
-rw-r--r-- | java/nio/channels/Channels.java | 6 |
11 files changed, 350 insertions, 152 deletions
@@ -1,3 +1,18 @@ +2006-05-01 Tom Tromey <tromey@redhat.com> + + * java/nio/ByteBufferImpl.java (compact): Don't reset position + in empty case. + * gnu/java/nio/ChannelReader.java (read): Synchronize. + (close): Synchronize. + * java/nio/ShortBufferImpl.java (compact): Rewrote. + * java/nio/LongBufferImpl.java (compact): Rewrote. + * java/nio/IntBufferImpl.java (compact): Rewrote. + * java/nio/FloatBufferImpl.java (compact): Rewrote. + * java/nio/DoubleBufferImpl.java (compact): Rewrote. + * java/nio/CharBufferImpl.java (compact): Rewrote. + * gnu/java/nio/ChannelWriter.java: New file. + * java/nio/channels/Channels.java (newWriter): Implemented. + 2006-05-01 Lillian Angel <langel@redhat.com> * java/util/SimpleTimeZone.java diff --git a/gnu/java/nio/ChannelReader.java b/gnu/java/nio/ChannelReader.java index 44fe6625a..1e7372d2e 100644 --- a/gnu/java/nio/ChannelReader.java +++ b/gnu/java/nio/ChannelReader.java @@ -92,120 +92,126 @@ public class ChannelReader extends Reader public int read(char[] buf, int offset, int count) throws IOException { - // I declared channel being null meaning that the reader is closed. - if (!channel.isOpen()) - throw new IOException("Reader was already closed."); - - // I declared decoder being null meaning that there is no more data to read - // and convert. - if (decoder == null) - return -1; - - // Stores the amount of character being read. It -1 so that if no conversion - // occured the caller will see this as an 'end of file'. - int sum = -1; - - // Copies any characters which may be left from the last invocation into the - // destination array. - if (charBuffer.remaining() > 0) + synchronized (lock) { - sum = Math.min(count, charBuffer.remaining()); - charBuffer.get(buf, offset, sum); - - // Updates the control variables according to the latest copy operation. - offset += sum; - count -= sum; - } - - // Copies the character which have not been put in the destination array to - // the beginning. If data is actually copied count will be 0. If no data is - // copied count is >0 and we can now convert some more characters. - charBuffer.compact(); - - int converted = 0; - boolean last = false; - - while (count != 0) - { - // Tries to convert some bytes (Which will intentionally fail in the - // first place because we have not read any bytes yet.) - CoderResult result = decoder.decode(byteBuffer, charBuffer, last); - if (result.isMalformed() || result.isUnmappable()) - { - // JDK throws exception when bytes are malformed for sure. - // FIXME: Unsure what happens when a character is simply - // unmappable. - result.throwException(); - } - - // Marks that we should end this loop regardless whether the caller - // wants more chars or not, when this was the last conversion. - if (last) + // I declared channel being null meaning that the reader is closed. + if (!channel.isOpen()) + throw new IOException("Reader was already closed."); + + // I declared decoder being null meaning that there is no more data to read + // and convert. + if (decoder == null) + return -1; + + // Stores the amount of character being read. It -1 so that if no conversion + // occured the caller will see this as an 'end of file'. + int sum = -1; + + // Copies any characters which may be left from the last invocation into the + // destination array. + if (charBuffer.remaining() > 0) { - decoder = null; + sum = Math.min(count, charBuffer.remaining()); + charBuffer.get(buf, offset, sum); + + // Updates the control variables according to the latest copy operation. + offset += sum; + count -= sum; } - else if (result.isUnderflow()) + + // Copies the character which have not been put in the destination array to + // the beginning. If data is actually copied count will be 0. If no data is + // copied count is >0 and we can now convert some more characters. + charBuffer.compact(); + + int converted = 0; + boolean last = false; + + while (count != 0) { - // We need more bytes to do the conversion. - - // Copies the not yet converted bytes to the beginning making it - // being able to receive more bytes. - byteBuffer.compact(); - - // Reads in another bunch of bytes for being converted. - if (channel.read(byteBuffer) == -1) + // Tries to convert some bytes (Which will intentionally fail in the + // first place because we have not read any bytes yet.) + CoderResult result = decoder.decode(byteBuffer, charBuffer, last); + if (result.isMalformed() || result.isUnmappable()) { - // If there is no more data available in the channel we mark - // that state for the final character conversion run which is - // done in the next loop iteration. - last = true; + // JDK throws exception when bytes are malformed for sure. + // FIXME: Unsure what happens when a character is simply + // unmappable. + result.throwException(); } - - // Prepares the byteBuffer for the next character conversion run. - byteBuffer.flip(); + + // Marks that we should end this loop regardless whether the caller + // wants more chars or not, when this was the last conversion. + if (last) + { + decoder = null; + } + else if (result.isUnderflow()) + { + // We need more bytes to do the conversion. + + // Copies the not yet converted bytes to the beginning making it + // being able to receive more bytes. + byteBuffer.compact(); + + // Reads in another bunch of bytes for being converted. + if (channel.read(byteBuffer) == -1) + { + // If there is no more data available in the channel we mark + // that state for the final character conversion run which is + // done in the next loop iteration. + last = true; + } + + // Prepares the byteBuffer for the next character conversion run. + byteBuffer.flip(); + } + + // Prepares the charBuffer for being drained. + charBuffer.flip(); + + converted = Math.min(count, charBuffer.remaining()); + charBuffer.get(buf, offset, converted); + + // Copies characters which have not yet being copied into the char-Array + // to the beginning making it possible to read them later (If data is + // really copied here, then the caller has received enough characters so + // far.). + charBuffer.compact(); + + // Updates the control variables according to the latest copy operation. + offset += converted; + count -= converted; + + // Updates the amount of transferred characters. + sum += converted; + + if (decoder == null) + { + break; + } + + // Now that more characters have been transfered we let the loop decide + // what to do next. } - - // Prepares the charBuffer for being drained. + + // Makes the charBuffer ready for reading on the next invocation. charBuffer.flip(); - - converted = Math.min(count, charBuffer.remaining()); - charBuffer.get(buf, offset, converted); - - // Copies characters which have not yet being copied into the char-Array - // to the beginning making it possible to read them later (If data is - // really copied here, then the caller has received enough characters so - // far.). - charBuffer.compact(); - - // Updates the control variables according to the latest copy operation. - offset += converted; - count -= converted; - - // Updates the amount of transferred characters. - sum += converted; - - if (decoder == null) - { - break; - } - - // Now that more characters have been transfered we let the loop decide - // what to do next. + + return sum; } - - // Makes the charBuffer ready for reading on the next invocation. - charBuffer.flip(); - - return sum; } public void close() throws IOException { - channel.close(); + synchronized (lock) + { + channel.close(); - // Makes sure all intermediate data is released by the decoder. - if (decoder != null) - decoder.reset(); + // Makes sure all intermediate data is released by the decoder. + if (decoder != null) + decoder.reset(); + } } } diff --git a/gnu/java/nio/ChannelWriter.java b/gnu/java/nio/ChannelWriter.java new file mode 100644 index 000000000..8e533ccbf --- /dev/null +++ b/gnu/java/nio/ChannelWriter.java @@ -0,0 +1,190 @@ +/* ChannelWriter.java -- nio / writer bridge + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.nio; + +import java.io.IOException; +import java.io.Writer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.CharsetEncoder; +import java.nio.charset.CoderResult; + +/** + * A Writer implementation that works by wrapping an NIO channel. + */ +public class ChannelWriter + extends Writer +{ + private static final int DEFAULT_BUFFER_CAP = 8192; + + /** + * The output channel. + */ + private WritableByteChannel byteChannel; + + /** + * The encoder to use. + */ + private CharsetEncoder enc; + + /** + * The byte buffer. Translated characters are stored here on their way out. + */ + private ByteBuffer byteBuffer; + + /** + * The character buffer. Characters are stored here on their way into + * the encoder. + */ + private CharBuffer charBuffer; + + private void writeBuffer() throws IOException + { + byteBuffer.flip(); + byteChannel.write(byteBuffer); + } + + /** + * Create a new instance, given the output byte channel, the encoder + * to use, and the minimum buffer capacity. + */ + public ChannelWriter(WritableByteChannel ch, CharsetEncoder enc, + int minBufferCap) + { + this.byteChannel = ch; + this.enc = enc; + if (minBufferCap == -1) + minBufferCap = DEFAULT_BUFFER_CAP; + this.byteBuffer + = ByteBuffer.allocate((int) (minBufferCap * enc.maxBytesPerChar())); + this.charBuffer = CharBuffer.allocate(minBufferCap); + this.charBuffer.clear(); + } + + /* (non-Javadoc) + * @see java.io.Writer#flush() + */ + public void flush() throws IOException + { + // Presumably if we have characters in our buffer, it is + // due to an underflow. So we don't bother trying to flush + // that here. + } + + /* (non-Javadoc) + * @see java.io.Writer#close() + */ + public void close() throws IOException + { + synchronized (lock) + { + if (enc == null) + throw new IOException("writer already closed"); + + byteBuffer.clear(); + charBuffer.flip(); + CoderResult res = enc.encode(charBuffer, byteBuffer, true); + if (res.isError() || res.isMalformed() || res.isUnmappable()) + res.throwException(); + writeBuffer(); + + byteBuffer.clear(); + res = enc.flush(byteBuffer); + if (res.isError() || res.isMalformed() || res.isUnmappable()) + res.throwException(); + writeBuffer(); + enc = null; + } + } + + /* (non-Javadoc) + * @see java.io.Writer#write(char[], int, int) + */ + public void write(char[] buf, int offset, int len) throws IOException + { + synchronized (lock) + { + if (enc == null) + throw new IOException("writer already closed"); + int lastLen = -1; + while (len > 0) + { + // Copy data into our character buffer. + int allowed = Math.min(charBuffer.remaining(), len); + charBuffer.put(buf, offset, allowed); + // Update for the next pass through the loop. + offset += allowed; + len -= allowed; + charBuffer.flip(); + // If we didn't make any progress, we want to clean up + // and save our state for the next write(). + if (len == lastLen) + { + if (len <= charBuffer.remaining()) + { + charBuffer.put(buf, offset, len); + charBuffer.flip(); + } + else + { + CharBuffer ncb = CharBuffer.allocate(charBuffer.length() + + len); + ncb.put(charBuffer); + ncb.put(buf, offset, len); + charBuffer = ncb; + } + break; + } + lastLen = len; + + // Convert. + byteBuffer.clear(); + CoderResult res = enc.encode(charBuffer, byteBuffer, false); + // Compact here, as we want to leave the buffer in the + // right state for any future put()s. + charBuffer.compact(); + if (res.isError() || res.isMalformed() || res.isUnmappable()) + res.throwException(); + // Write the byte buffer to the output channel. + writeBuffer(); + } + } + } +} diff --git a/java/nio/ByteBufferImpl.java b/java/nio/ByteBufferImpl.java index 48d715200..cbe627b06 100644 --- a/java/nio/ByteBufferImpl.java +++ b/java/nio/ByteBufferImpl.java @@ -120,13 +120,8 @@ final class ByteBufferImpl extends ByteBuffer int count = remaining(); shiftDown(0, pos, count); position(count); - limit(capacity()); - } - else - { - position(limit()); - limit(capacity()); } + limit(capacity()); return this; } diff --git a/java/nio/CharBufferImpl.java b/java/nio/CharBufferImpl.java index 33f8dab98..e6097cb75 100644 --- a/java/nio/CharBufferImpl.java +++ b/java/nio/CharBufferImpl.java @@ -90,15 +90,14 @@ final class CharBufferImpl extends CharBuffer { checkIfReadOnly(); mark = -1; - int copied = 0; - - while (remaining () > 0) + int p = position(); + int n = limit() - p; + if (n > 0) { - put (copied, get ()); - copied++; + System.arraycopy(backing_buffer, array_offset + p, + backing_buffer, array_offset, n); } - - position (copied); + position(n); limit(capacity()); return this; } diff --git a/java/nio/DoubleBufferImpl.java b/java/nio/DoubleBufferImpl.java index 248ab45e7..98e8e974f 100644 --- a/java/nio/DoubleBufferImpl.java +++ b/java/nio/DoubleBufferImpl.java @@ -82,15 +82,14 @@ final class DoubleBufferImpl extends DoubleBuffer { checkIfReadOnly(); mark = -1; - int copied = 0; - - while (remaining () > 0) + int p = position(); + int n = limit() - p; + if (n > 0) { - put (copied, get ()); - copied++; + System.arraycopy(backing_buffer, array_offset + p, + backing_buffer, array_offset, n); } - - position (copied); + position(n); limit(capacity()); return this; } diff --git a/java/nio/FloatBufferImpl.java b/java/nio/FloatBufferImpl.java index b4868780c..f1182ba38 100644 --- a/java/nio/FloatBufferImpl.java +++ b/java/nio/FloatBufferImpl.java @@ -82,15 +82,14 @@ final class FloatBufferImpl extends FloatBuffer { checkIfReadOnly(); mark = -1; - int copied = 0; - - while (remaining () > 0) + int p = position(); + int n = limit() - p; + if (n > 0) { - put (copied, get ()); - copied++; + System.arraycopy(backing_buffer, array_offset + p, + backing_buffer, array_offset, n); } - - position (copied); + position(n); limit(capacity()); return this; } diff --git a/java/nio/IntBufferImpl.java b/java/nio/IntBufferImpl.java index 22657482b..2bd184244 100644 --- a/java/nio/IntBufferImpl.java +++ b/java/nio/IntBufferImpl.java @@ -82,15 +82,14 @@ final class IntBufferImpl extends IntBuffer { checkIfReadOnly(); mark = -1; - int copied = 0; - - while (remaining () > 0) + int p = position(); + int n = limit() - p; + if (n > 0) { - put (copied, get ()); - copied++; + System.arraycopy(backing_buffer, array_offset + p, + backing_buffer, array_offset, n); } - - position (copied); + position(n); limit(capacity()); return this; } diff --git a/java/nio/LongBufferImpl.java b/java/nio/LongBufferImpl.java index 8772f618c..c04c41775 100644 --- a/java/nio/LongBufferImpl.java +++ b/java/nio/LongBufferImpl.java @@ -82,15 +82,14 @@ final class LongBufferImpl extends LongBuffer { checkIfReadOnly(); mark = -1; - int copied = 0; - - while (remaining () > 0) + int p = position(); + int n = limit() - p; + if (n > 0) { - put (copied, get ()); - copied++; + System.arraycopy(backing_buffer, array_offset + p, + backing_buffer, array_offset, n); } - - position (copied); + position(n); limit(capacity()); return this; } diff --git a/java/nio/ShortBufferImpl.java b/java/nio/ShortBufferImpl.java index ee5bff2f9..50f65ecbf 100644 --- a/java/nio/ShortBufferImpl.java +++ b/java/nio/ShortBufferImpl.java @@ -82,15 +82,14 @@ final class ShortBufferImpl extends ShortBuffer { checkIfReadOnly(); mark = -1; - int copied = 0; - - while (remaining () > 0) + int p = position(); + int n = limit() - p; + if (n > 0) { - put (copied, get ()); - copied++; + System.arraycopy(backing_buffer, array_offset + p, + backing_buffer, array_offset, n); } - - position (copied); + position(n); limit(capacity()); return this; } diff --git a/java/nio/channels/Channels.java b/java/nio/channels/Channels.java index a53cc2c74..382a3d705 100644 --- a/java/nio/channels/Channels.java +++ b/java/nio/channels/Channels.java @@ -38,8 +38,8 @@ exception statement from your version. */ package java.nio.channels; -import gnu.classpath.NotImplementedException; import gnu.java.nio.ChannelReader; +import gnu.java.nio.ChannelWriter; import gnu.java.nio.InputStreamChannel; import gnu.java.nio.OutputStreamChannel; @@ -126,10 +126,8 @@ public final class Channels */ public static Writer newWriter(WritableByteChannel ch, CharsetEncoder enc, int minBufferCap) - throws NotImplementedException { - // FIXME: implement java.nio.channels.Channel.newWriter(WritableByteChannel, CharsetEncoder, int) - throw new Error("not implemented"); + return new ChannelWriter(ch, enc, minBufferCap); } /** |