mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
381
src/java.base/share/classes/sun/nio/cs/StreamDecoder.java
Normal file
381
src/java.base/share/classes/sun/nio/cs/StreamDecoder.java
Normal file
|
@ -0,0 +1,381 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
package sun.nio.cs;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.charset.*;
|
||||
|
||||
public class StreamDecoder extends Reader
|
||||
{
|
||||
|
||||
private static final int MIN_BYTE_BUFFER_SIZE = 32;
|
||||
private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;
|
||||
|
||||
private volatile boolean closed;
|
||||
|
||||
private void ensureOpen() throws IOException {
|
||||
if (closed)
|
||||
throw new IOException("Stream closed");
|
||||
}
|
||||
|
||||
// In order to handle surrogates properly we must never try to produce
|
||||
// fewer than two characters at a time. If we're only asked to return one
|
||||
// character then the other is saved here to be returned later.
|
||||
//
|
||||
private boolean haveLeftoverChar = false;
|
||||
private char leftoverChar;
|
||||
|
||||
|
||||
// Factories for java.io.InputStreamReader
|
||||
|
||||
public static StreamDecoder forInputStreamReader(InputStream in,
|
||||
Object lock,
|
||||
String charsetName)
|
||||
throws UnsupportedEncodingException
|
||||
{
|
||||
String csn = charsetName;
|
||||
if (csn == null)
|
||||
csn = Charset.defaultCharset().name();
|
||||
try {
|
||||
if (Charset.isSupported(csn))
|
||||
return new StreamDecoder(in, lock, Charset.forName(csn));
|
||||
} catch (IllegalCharsetNameException x) { }
|
||||
throw new UnsupportedEncodingException (csn);
|
||||
}
|
||||
|
||||
public static StreamDecoder forInputStreamReader(InputStream in,
|
||||
Object lock,
|
||||
Charset cs)
|
||||
{
|
||||
return new StreamDecoder(in, lock, cs);
|
||||
}
|
||||
|
||||
public static StreamDecoder forInputStreamReader(InputStream in,
|
||||
Object lock,
|
||||
CharsetDecoder dec)
|
||||
{
|
||||
return new StreamDecoder(in, lock, dec);
|
||||
}
|
||||
|
||||
|
||||
// Factory for java.nio.channels.Channels.newReader
|
||||
|
||||
public static StreamDecoder forDecoder(ReadableByteChannel ch,
|
||||
CharsetDecoder dec,
|
||||
int minBufferCap)
|
||||
{
|
||||
return new StreamDecoder(ch, dec, minBufferCap);
|
||||
}
|
||||
|
||||
|
||||
// -- Public methods corresponding to those in InputStreamReader --
|
||||
|
||||
// All synchronization and state/argument checking is done in these public
|
||||
// methods; the concrete stream-decoder subclasses defined below need not
|
||||
// do any such checking.
|
||||
|
||||
public String getEncoding() {
|
||||
if (isOpen())
|
||||
return encodingName();
|
||||
return null;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
return read0();
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private int read0() throws IOException {
|
||||
synchronized (lock) {
|
||||
|
||||
// Return the leftover char, if there is one
|
||||
if (haveLeftoverChar) {
|
||||
haveLeftoverChar = false;
|
||||
return leftoverChar;
|
||||
}
|
||||
|
||||
// Convert more bytes
|
||||
char cb[] = new char[2];
|
||||
int n = read(cb, 0, 2);
|
||||
switch (n) {
|
||||
case -1:
|
||||
return -1;
|
||||
case 2:
|
||||
leftoverChar = cb[1];
|
||||
haveLeftoverChar = true;
|
||||
// FALL THROUGH
|
||||
case 1:
|
||||
return cb[0];
|
||||
default:
|
||||
assert false : n;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int read(char cbuf[], int offset, int length) throws IOException {
|
||||
int off = offset;
|
||||
int len = length;
|
||||
synchronized (lock) {
|
||||
ensureOpen();
|
||||
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
|
||||
((off + len) > cbuf.length) || ((off + len) < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
int n = 0;
|
||||
|
||||
if (haveLeftoverChar) {
|
||||
// Copy the leftover char into the buffer
|
||||
cbuf[off] = leftoverChar;
|
||||
off++; len--;
|
||||
haveLeftoverChar = false;
|
||||
n = 1;
|
||||
if ((len == 0) || !implReady())
|
||||
// Return now if this is all we can produce w/o blocking
|
||||
return n;
|
||||
}
|
||||
|
||||
if (len == 1) {
|
||||
// Treat single-character array reads just like read()
|
||||
int c = read0();
|
||||
if (c == -1)
|
||||
return (n == 0) ? -1 : n;
|
||||
cbuf[off] = (char)c;
|
||||
return n + 1;
|
||||
}
|
||||
|
||||
return n + implRead(cbuf, off, off + len);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean ready() throws IOException {
|
||||
synchronized (lock) {
|
||||
ensureOpen();
|
||||
return haveLeftoverChar || implReady();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
synchronized (lock) {
|
||||
if (closed)
|
||||
return;
|
||||
implClose();
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOpen() {
|
||||
return !closed;
|
||||
}
|
||||
|
||||
|
||||
// -- Charset-based stream decoder impl --
|
||||
|
||||
// In the early stages of the build we haven't yet built the NIO native
|
||||
// code, so guard against that by catching the first UnsatisfiedLinkError
|
||||
// and setting this flag so that later attempts fail quickly.
|
||||
//
|
||||
private static volatile boolean channelsAvailable = true;
|
||||
|
||||
private static FileChannel getChannel(FileInputStream in) {
|
||||
if (!channelsAvailable)
|
||||
return null;
|
||||
try {
|
||||
return in.getChannel();
|
||||
} catch (UnsatisfiedLinkError x) {
|
||||
channelsAvailable = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Charset cs;
|
||||
private CharsetDecoder decoder;
|
||||
private ByteBuffer bb;
|
||||
|
||||
// Exactly one of these is non-null
|
||||
private InputStream in;
|
||||
private ReadableByteChannel ch;
|
||||
|
||||
StreamDecoder(InputStream in, Object lock, Charset cs) {
|
||||
this(in, lock,
|
||||
cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPLACE)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPLACE));
|
||||
}
|
||||
|
||||
StreamDecoder(InputStream in, Object lock, CharsetDecoder dec) {
|
||||
super(lock);
|
||||
this.cs = dec.charset();
|
||||
this.decoder = dec;
|
||||
|
||||
// This path disabled until direct buffers are faster
|
||||
if (false && in instanceof FileInputStream) {
|
||||
ch = getChannel((FileInputStream)in);
|
||||
if (ch != null)
|
||||
bb = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);
|
||||
}
|
||||
if (ch == null) {
|
||||
this.in = in;
|
||||
this.ch = null;
|
||||
bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
|
||||
}
|
||||
bb.flip(); // So that bb is initially empty
|
||||
}
|
||||
|
||||
StreamDecoder(ReadableByteChannel ch, CharsetDecoder dec, int mbc) {
|
||||
this.in = null;
|
||||
this.ch = ch;
|
||||
this.decoder = dec;
|
||||
this.cs = dec.charset();
|
||||
this.bb = ByteBuffer.allocate(mbc < 0
|
||||
? DEFAULT_BYTE_BUFFER_SIZE
|
||||
: (mbc < MIN_BYTE_BUFFER_SIZE
|
||||
? MIN_BYTE_BUFFER_SIZE
|
||||
: mbc));
|
||||
bb.flip();
|
||||
}
|
||||
|
||||
private int readBytes() throws IOException {
|
||||
bb.compact();
|
||||
try {
|
||||
if (ch != null) {
|
||||
// Read from the channel
|
||||
int n = ch.read(bb);
|
||||
if (n < 0)
|
||||
return n;
|
||||
} else {
|
||||
// Read from the input stream, and then update the buffer
|
||||
int lim = bb.limit();
|
||||
int pos = bb.position();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
assert rem > 0;
|
||||
int n = in.read(bb.array(), bb.arrayOffset() + pos, rem);
|
||||
if (n < 0)
|
||||
return n;
|
||||
if (n == 0)
|
||||
throw new IOException("Underlying input stream returned zero bytes");
|
||||
assert (n <= rem) : "n = " + n + ", rem = " + rem;
|
||||
bb.position(pos + n);
|
||||
}
|
||||
} finally {
|
||||
// Flip even when an IOException is thrown,
|
||||
// otherwise the stream will stutter
|
||||
bb.flip();
|
||||
}
|
||||
|
||||
int rem = bb.remaining();
|
||||
assert (rem != 0) : rem;
|
||||
return rem;
|
||||
}
|
||||
|
||||
int implRead(char[] cbuf, int off, int end) throws IOException {
|
||||
|
||||
// In order to handle surrogate pairs, this method requires that
|
||||
// the invoker attempt to read at least two characters. Saving the
|
||||
// extra character, if any, at a higher level is easier than trying
|
||||
// to deal with it here.
|
||||
assert (end - off > 1);
|
||||
|
||||
CharBuffer cb = CharBuffer.wrap(cbuf, off, end - off);
|
||||
if (cb.position() != 0)
|
||||
// Ensure that cb[0] == cbuf[off]
|
||||
cb = cb.slice();
|
||||
|
||||
boolean eof = false;
|
||||
for (;;) {
|
||||
CoderResult cr = decoder.decode(bb, cb, eof);
|
||||
if (cr.isUnderflow()) {
|
||||
if (eof)
|
||||
break;
|
||||
if (!cb.hasRemaining())
|
||||
break;
|
||||
if ((cb.position() > 0) && !inReady())
|
||||
break; // Block at most once
|
||||
int n = readBytes();
|
||||
if (n < 0) {
|
||||
eof = true;
|
||||
if ((cb.position() == 0) && (!bb.hasRemaining()))
|
||||
break;
|
||||
decoder.reset();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (cr.isOverflow()) {
|
||||
assert cb.position() > 0;
|
||||
break;
|
||||
}
|
||||
cr.throwException();
|
||||
}
|
||||
|
||||
if (eof) {
|
||||
// ## Need to flush decoder
|
||||
decoder.reset();
|
||||
}
|
||||
|
||||
if (cb.position() == 0) {
|
||||
if (eof)
|
||||
return -1;
|
||||
assert false;
|
||||
}
|
||||
return cb.position();
|
||||
}
|
||||
|
||||
String encodingName() {
|
||||
return ((cs instanceof HistoricallyNamedCharset)
|
||||
? ((HistoricallyNamedCharset)cs).historicalName()
|
||||
: cs.name());
|
||||
}
|
||||
|
||||
private boolean inReady() {
|
||||
try {
|
||||
return (((in != null) && (in.available() > 0))
|
||||
|| (ch instanceof FileChannel)); // ## RBC.available()?
|
||||
} catch (IOException x) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
boolean implReady() {
|
||||
return bb.hasRemaining() || inReady();
|
||||
}
|
||||
|
||||
void implClose() throws IOException {
|
||||
if (ch != null)
|
||||
ch.close();
|
||||
else
|
||||
in.close();
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue