diff options
Diffstat (limited to 'plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java')
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java new file mode 100644 index 0000000000..b9291ef374 --- /dev/null +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/io/ReaderInputStream.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020 Eike Stepper (Loehne, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.util.io; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +/** + * An input stream for reading a {@link Reader}. + * + * @author Eike Stepper + * @since 3.13 + */ +public class ReaderInputStream extends InputStream +{ + private static final int MASK = 0xFF; + + private final Charset charset; + + private Reader reader; + + private CharBuffer chars = CharBuffer.allocate(IOUtil.DEFAULT_BUFFER_SIZE); + + private ByteBuffer bytes; + + public ReaderInputStream(Reader reader, String encoding) throws IOException + { + this.reader = reader; + charset = encoding == null ? StandardCharsets.UTF_8 : Charset.forName(encoding); + } + + public ReaderInputStream(Reader reader) throws IOException + { + this(reader, null); + } + + @Override + public int available() throws IOException + { + checkClosed(); + ensureBytes(); + + if (bytes == null) + { + return 0; + } + + return bytes.remaining(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + checkClosed(); + + if (len == 0) + { + return 0; + } + + ensureBytes(); + if (bytes == null) + { + return IOUtil.EOF; + } + + int count = 0; + do + { + ensureBytes(); + + if (bytes == null) + { + // No more to read. + break; + } + + int toRead = Math.min(bytes.remaining(), len - count); + bytes.get(b, off + count, toRead); + count = count + toRead; + } while (count < len); + + return count; + } + + @Override + public int read() throws IOException + { + checkClosed(); + + ensureBytes(); + if (bytes == null) + { + return IOUtil.EOF; + } + + return bytes.get() & MASK; + } + + @Override + public void close() throws IOException + { + if (reader != null) + { + reader.close(); + reader = null; + bytes = null; + chars = null; + } + } + + private void ensureBytes() throws IOException + { + if (bytes == null || !bytes.hasRemaining()) + { + checkClosed(); + + Buffer buffer = chars; + buffer.rewind(); + + int count = reader.read(chars); + if (count > 0) + { + buffer.flip(); + bytes = charset.encode(chars); + } + else + { + bytes = null; + } + } + } + + private void checkClosed() throws IOException + { + if (reader == null) + { + throw new IOException("Reader is closed"); //$NON-NLS-1$ + } + } +} |