8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2009, 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;
/*
* FastPath byte[]->char[] decoder, REPLACE on malformed or
* unmappable input.
*/
public interface ArrayDecoder {
int decode(byte[] src, int off, int len, char[] dst);
default boolean isASCIICompatible() {
return false;
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2009, 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;
/*
* FastPath char[]/byte[] -> byte[] encoder, REPLACE on malformed input or
* unmappable input.
*/
public interface ArrayEncoder {
// is only used by j.u.zip.ZipCoder for utf8
int encode(char[] src, int off, int len, byte[] dst);
default int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
return -1;
}
default int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
return -1;
}
default boolean isASCIICompatible() {
return false;
}
}

View file

@ -0,0 +1,604 @@
/*
* Copyright (c) 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.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/* Legal CESU-8 Byte Sequences
*
* # Code Points Bits Bit/Byte pattern
* 1 7 0xxxxxxx
* U+0000..U+007F 00..7F
*
* 2 11 110xxxxx 10xxxxxx
* U+0080..U+07FF C2..DF 80..BF
*
* 3 16 1110xxxx 10xxxxxx 10xxxxxx
* U+0800..U+0FFF E0 A0..BF 80..BF
* U+1000..U+FFFF E1..EF 80..BF 80..BF
*
*/
class CESU_8 extends Unicode
{
public CESU_8() {
super("CESU-8", StandardCharsets.aliases_CESU_8());
}
public String historicalName() {
return "CESU8";
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static final void updatePositions(Buffer src, int sp,
Buffer dst, int dp) {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
private static class Decoder extends CharsetDecoder
implements ArrayDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
private static boolean isNotContinuation(int b) {
return (b & 0xc0) != 0x80;
}
// [E0] [A0..BF] [80..BF]
// [E1..EF] [80..BF] [80..BF]
private static boolean isMalformed3(int b1, int b2, int b3) {
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
(b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
}
// only used when there is only one byte left in src buffer
private static boolean isMalformed3_2(int b1, int b2) {
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
(b2 & 0xc0) != 0x80;
}
// [F0] [90..BF] [80..BF] [80..BF]
// [F1..F3] [80..BF] [80..BF] [80..BF]
// [F4] [80..8F] [80..BF] [80..BF]
// only check 80-be range here, the [0xf0,0x80...] and [0xf4,0x90-...]
// will be checked by Character.isSupplementaryCodePoint(uc)
private static boolean isMalformed4(int b2, int b3, int b4) {
return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
(b4 & 0xc0) != 0x80;
}
// only used when there is less than 4 bytes left in src buffer
private static boolean isMalformed4_2(int b1, int b2) {
return (b1 == 0xf0 && b2 == 0x90) ||
(b2 & 0xc0) != 0x80;
}
private static boolean isMalformed4_3(int b3) {
return (b3 & 0xc0) != 0x80;
}
private static CoderResult malformedN(ByteBuffer src, int nb) {
switch (nb) {
case 1:
case 2: // always 1
return CoderResult.malformedForLength(1);
case 3:
int b1 = src.get();
int b2 = src.get(); // no need to lookup b3
return CoderResult.malformedForLength(
((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
isNotContinuation(b2)) ? 1 : 2);
case 4: // we don't care the speed here
b1 = src.get() & 0xff;
b2 = src.get() & 0xff;
if (b1 > 0xf4 ||
(b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
isNotContinuation(b2))
return CoderResult.malformedForLength(1);
if (isNotContinuation(src.get()))
return CoderResult.malformedForLength(2);
return CoderResult.malformedForLength(3);
default:
assert false;
return null;
}
}
private static CoderResult malformed(ByteBuffer src, int sp,
CharBuffer dst, int dp,
int nb)
{
src.position(sp - src.arrayOffset());
CoderResult cr = malformedN(src, nb);
updatePositions(src, sp, dst, dp);
return cr;
}
private static CoderResult malformed(ByteBuffer src,
int mark, int nb)
{
src.position(mark);
CoderResult cr = malformedN(src, nb);
src.position(mark);
return cr;
}
private static CoderResult malformedForLength(ByteBuffer src,
int sp,
CharBuffer dst,
int dp,
int malformedNB)
{
updatePositions(src, sp, dst, dp);
return CoderResult.malformedForLength(malformedNB);
}
private static CoderResult malformedForLength(ByteBuffer src,
int mark,
int malformedNB)
{
src.position(mark);
return CoderResult.malformedForLength(malformedNB);
}
private static CoderResult xflow(Buffer src, int sp, int sl,
Buffer dst, int dp, int nb) {
updatePositions(src, sp, dst, dp);
return (nb == 0 || sl - sp < nb)
? CoderResult.UNDERFLOW : CoderResult.OVERFLOW;
}
private static CoderResult xflow(Buffer src, int mark, int nb) {
src.position(mark);
return (nb == 0 || src.remaining() < nb)
? CoderResult.UNDERFLOW : CoderResult.OVERFLOW;
}
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
// This method is optimized for ASCII input.
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] >= 0)
da[dp++] = (char) sa[sp++];
while (sp < sl) {
int b1 = sa[sp];
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
if (dp >= dl)
return xflow(src, sp, sl, dst, dp, 1);
da[dp++] = (char) b1;
sp++;
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
if (sl - sp < 2 || dp >= dl)
return xflow(src, sp, sl, dst, dp, 2);
int b2 = sa[sp + 1];
if (isNotContinuation(b2))
return malformedForLength(src, sp, dst, dp, 1);
da[dp++] = (char) (((b1 << 6) ^ b2)
^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0)));
sp += 2;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
int srcRemaining = sl - sp;
if (srcRemaining < 3 || dp >= dl) {
if (srcRemaining > 1 && isMalformed3_2(b1, sa[sp + 1]))
return malformedForLength(src, sp, dst, dp, 1);
return xflow(src, sp, sl, dst, dp, 3);
}
int b2 = sa[sp + 1];
int b3 = sa[sp + 2];
if (isMalformed3(b1, b2, b3))
return malformed(src, sp, dst, dp, 3);
da[dp++] = (char)
((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
sp += 3;
} else {
return malformed(src, sp, dst, dp, 1);
}
}
return xflow(src, sp, sl, dst, dp, 0);
}
private CoderResult decodeBufferLoop(ByteBuffer src,
CharBuffer dst)
{
int mark = src.position();
int limit = src.limit();
while (mark < limit) {
int b1 = src.get();
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
if (dst.remaining() < 1)
return xflow(src, mark, 1); // overflow
dst.put((char) b1);
mark++;
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
if (limit - mark < 2|| dst.remaining() < 1)
return xflow(src, mark, 2);
int b2 = src.get();
if (isNotContinuation(b2))
return malformedForLength(src, mark, 1);
dst.put((char) (((b1 << 6) ^ b2)
^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0))));
mark += 2;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
int srcRemaining = limit - mark;
if (srcRemaining < 3 || dst.remaining() < 1) {
if (srcRemaining > 1 && isMalformed3_2(b1, src.get()))
return malformedForLength(src, mark, 1);
return xflow(src, mark, 3);
}
int b2 = src.get();
int b3 = src.get();
if (isMalformed3(b1, b2, b3))
return malformed(src, mark, 3);
dst.put((char)
((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0)))));
mark += 3;
} else {
return malformed(src, mark, 1);
}
}
return xflow(src, mark, 0);
}
protected CoderResult decodeLoop(ByteBuffer src,
CharBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return decodeArrayLoop(src, dst);
else
return decodeBufferLoop(src, dst);
}
private static ByteBuffer getByteBuffer(ByteBuffer bb, byte[] ba, int sp)
{
if (bb == null)
bb = ByteBuffer.wrap(ba);
bb.position(sp);
return bb;
}
// returns -1 if there is/are malformed byte(s) and the
// "action" for malformed input is not REPLACE.
public int decode(byte[] sa, int sp, int len, char[] da) {
final int sl = sp + len;
int dp = 0;
int dlASCII = Math.min(len, da.length);
ByteBuffer bb = null; // only necessary if malformed
// ASCII only optimized loop
while (dp < dlASCII && sa[sp] >= 0)
da[dp++] = (char) sa[sp++];
while (sp < sl) {
int b1 = sa[sp++];
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
da[dp++] = (char) b1;
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
if (sp < sl) {
int b2 = sa[sp++];
if (isNotContinuation(b2)) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
sp--; // malformedN(bb, 2) always returns 1
} else {
da[dp++] = (char) (((b1 << 6) ^ b2)^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0)));
}
continue;
}
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
return dp;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
if (sp + 1 < sl) {
int b2 = sa[sp++];
int b3 = sa[sp++];
if (isMalformed3(b1, b2, b3)) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
sp -=3;
bb = getByteBuffer(bb, sa, sp);
sp += malformedN(bb, 3).length();
} else {
da[dp++] = (char)((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
}
continue;
}
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
if (sp < sl && isMalformed3_2(b1, sa[sp])) {
da[dp++] = replacement().charAt(0);
continue;
}
da[dp++] = replacement().charAt(0);
return dp;
} else {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
}
}
return dp;
}
}
private static class Encoder extends CharsetEncoder
implements ArrayEncoder {
private Encoder(Charset cs) {
super(cs, 1.1f, 3.0f);
}
public boolean canEncode(char c) {
return !Character.isSurrogate(c);
}
public boolean isLegalReplacement(byte[] repl) {
return ((repl.length == 1 && repl[0] >= 0) ||
super.isLegalReplacement(repl));
}
private static CoderResult overflow(CharBuffer src, int sp,
ByteBuffer dst, int dp) {
updatePositions(src, sp, dst, dp);
return CoderResult.OVERFLOW;
}
private static CoderResult overflow(CharBuffer src, int mark) {
src.position(mark);
return CoderResult.OVERFLOW;
}
private static void to3Bytes(byte[] da, int dp, char c) {
da[dp] = (byte)(0xe0 | ((c >> 12)));
da[dp + 1] = (byte)(0x80 | ((c >> 6) & 0x3f));
da[dp + 2] = (byte)(0x80 | (c & 0x3f));
}
private static void to3Bytes(ByteBuffer dst, char c) {
dst.put((byte)(0xe0 | ((c >> 12))));
dst.put((byte)(0x80 | ((c >> 6) & 0x3f)));
dst.put((byte)(0x80 | (c & 0x3f)));
}
private Surrogate.Parser sgp;
private char[] c2;
private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst)
{
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
while (sp < sl) {
char c = sa[sp];
if (c < 0x80) {
// Have at most seven bits
if (dp >= dl)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
if (dl - dp < 2)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, sa, sp, sl);
if (uc < 0) {
updatePositions(src, sp, dst, dp);
return sgp.error();
}
if (dl - dp < 6)
return overflow(src, sp, dst, dp);
to3Bytes(da, dp, Character.highSurrogate(uc));
dp += 3;
to3Bytes(da, dp, Character.lowSurrogate(uc));
dp += 3;
sp++; // 2 chars
} else {
// 3 bytes, 16 bits
if (dl - dp < 3)
return overflow(src, sp, dst, dp);
to3Bytes(da, dp, c);
dp += 3;
}
sp++;
}
updatePositions(src, sp, dst, dp);
return CoderResult.UNDERFLOW;
}
private CoderResult encodeBufferLoop(CharBuffer src,
ByteBuffer dst)
{
int mark = src.position();
while (src.hasRemaining()) {
char c = src.get();
if (c < 0x80) {
// Have at most seven bits
if (!dst.hasRemaining())
return overflow(src, mark);
dst.put((byte)c);
} else if (c < 0x800) {
// 2 bytes, 11 bits
if (dst.remaining() < 2)
return overflow(src, mark);
dst.put((byte)(0xc0 | (c >> 6)));
dst.put((byte)(0x80 | (c & 0x3f)));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, src);
if (uc < 0) {
src.position(mark);
return sgp.error();
}
if (dst.remaining() < 6)
return overflow(src, mark);
to3Bytes(dst, Character.highSurrogate(uc));
to3Bytes(dst, Character.lowSurrogate(uc));
mark++; // 2 chars
} else {
// 3 bytes, 16 bits
if (dst.remaining() < 3)
return overflow(src, mark);
to3Bytes(dst, c);
}
mark++;
}
src.position(mark);
return CoderResult.UNDERFLOW;
}
protected final CoderResult encodeLoop(CharBuffer src,
ByteBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return encodeArrayLoop(src, dst);
else
return encodeBufferLoop(src, dst);
}
// returns -1 if there is malformed char(s) and the
// "action" for malformed input is not REPLACE.
public int encode(char[] sa, int sp, int len, byte[] da) {
int sl = sp + len;
int dp = 0;
int dlASCII = dp + Math.min(len, da.length);
// ASCII only optimized loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
while (sp < sl) {
char c = sa[sp++];
if (c < 0x80) {
// Have at most seven bits
da[dp++] = (byte)c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, sa, sp - 1, sl);
if (uc < 0) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement()[0];
} else {
to3Bytes(da, dp, Character.highSurrogate(uc));
dp += 3;
to3Bytes(da, dp, Character.lowSurrogate(uc));
dp += 3;
sp++; // 2 chars
}
} else {
// 3 bytes, 16 bits
to3Bytes(da, dp, c);
dp += 3;
}
}
return dp;
}
}
}

View file

@ -0,0 +1,353 @@
/*
* Copyright (c) 2008, 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.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.*;
import java.security.*;
public class CharsetMapping {
public static final char UNMAPPABLE_DECODING = '\uFFFD';
public static final int UNMAPPABLE_ENCODING = 0xFFFD;
char[] b2cSB; //singlebyte b->c
char[] b2cDB1; //dobulebyte b->c /db1
char[] b2cDB2; //dobulebyte b->c /db2
int b2Min, b2Max; //min/max(start/end) value of 2nd byte
int b1MinDB1, b1MaxDB1; //min/Max(start/end) value of 1st byte/db1
int b1MinDB2, b1MaxDB2; //min/Max(start/end) value of 1st byte/db2
int dbSegSize;
char[] c2b;
char[] c2bIndex;
// Supplementary
char[] b2cSupp;
char[] c2bSupp;
// Composite
Entry[] b2cComp;
Entry[] c2bComp;
public char decodeSingle(int b) {
return b2cSB[b];
}
public char decodeDouble(int b1, int b2) {
if (b2 >= b2Min && b2 < b2Max) {
b2 -= b2Min;
if (b1 >= b1MinDB1 && b1 <= b1MaxDB1) {
b1 -= b1MinDB1;
return b2cDB1[b1 * dbSegSize + b2];
}
if (b1 >= b1MinDB2 && b1 <= b1MaxDB2) {
b1 -= b1MinDB2;
return b2cDB2[b1 * dbSegSize + b2];
}
}
return UNMAPPABLE_DECODING;
}
// for jis0213 all supplementary characters are in 0x2xxxx range,
// so only the xxxx part is now stored, should actually store the
// codepoint value instead.
public char[] decodeSurrogate(int db, char[] cc) {
int end = b2cSupp.length / 2;
int i = Arrays.binarySearch(b2cSupp, 0, end, (char)db);
if (i >= 0) {
Character.toChars(b2cSupp[end + i] + 0x20000, cc, 0);
return cc;
}
return null;
}
public char[] decodeComposite(Entry comp, char[] cc) {
int i = findBytes(b2cComp, comp);
if (i >= 0) {
cc[0] = (char)b2cComp[i].cp;
cc[1] = (char)b2cComp[i].cp2;
return cc;
}
return null;
}
public int encodeChar(char ch) {
int index = c2bIndex[ch >> 8];
if (index == 0xffff)
return UNMAPPABLE_ENCODING;
return c2b[index + (ch & 0xff)];
}
public int encodeSurrogate(char hi, char lo) {
int cp = Character.toCodePoint(hi, lo);
if (cp < 0x20000 || cp >= 0x30000)
return UNMAPPABLE_ENCODING;
int end = c2bSupp.length / 2;
int i = Arrays.binarySearch(c2bSupp, 0, end, (char)cp);
if (i >= 0)
return c2bSupp[end + i];
return UNMAPPABLE_ENCODING;
}
public boolean isCompositeBase(Entry comp) {
if (comp.cp <= 0x31f7 && comp.cp >= 0xe6) {
return (findCP(c2bComp, comp) >= 0);
}
return false;
}
public int encodeComposite(Entry comp) {
int i = findComp(c2bComp, comp);
if (i >= 0)
return c2bComp[i].bs;
return UNMAPPABLE_ENCODING;
}
// init the CharsetMapping object from the .dat binary file
public static CharsetMapping get(final InputStream is) {
return AccessController.doPrivileged(new PrivilegedAction<>() {
public CharsetMapping run() {
return new CharsetMapping().load(is);
}
});
}
public static class Entry {
public int bs; //byte sequence reps
public int cp; //Unicode codepoint
public int cp2; //CC of composite
}
static Comparator<Entry> comparatorBytes =
new Comparator<Entry>() {
public int compare(Entry m1, Entry m2) {
return m1.bs - m2.bs;
}
public boolean equals(Object obj) {
return this == obj;
}
};
static Comparator<Entry> comparatorCP =
new Comparator<Entry>() {
public int compare(Entry m1, Entry m2) {
return m1.cp - m2.cp;
}
public boolean equals(Object obj) {
return this == obj;
}
};
static Comparator<Entry> comparatorComp =
new Comparator<Entry>() {
public int compare(Entry m1, Entry m2) {
int v = m1.cp - m2.cp;
if (v == 0)
v = m1.cp2 - m2.cp2;
return v;
}
public boolean equals(Object obj) {
return this == obj;
}
};
static int findBytes(Entry[] a, Entry k) {
return Arrays.binarySearch(a, 0, a.length, k, comparatorBytes);
}
static int findCP(Entry[] a, Entry k) {
return Arrays.binarySearch(a, 0, a.length, k, comparatorCP);
}
static int findComp(Entry[] a, Entry k) {
return Arrays.binarySearch(a, 0, a.length, k, comparatorComp);
}
/*****************************************************************************/
// tags of different charset mapping tables
private static final int MAP_SINGLEBYTE = 0x1; // 0..256 : c
private static final int MAP_DOUBLEBYTE1 = 0x2; // min..max: c
private static final int MAP_DOUBLEBYTE2 = 0x3; // min..max: c [DB2]
private static final int MAP_SUPPLEMENT = 0x5; // db,c
private static final int MAP_SUPPLEMENT_C2B = 0x6; // c,db
private static final int MAP_COMPOSITE = 0x7; // db,base,cc
private static final int MAP_INDEXC2B = 0x8; // index table of c->bb
private static final boolean readNBytes(InputStream in, byte[] bb, int N)
throws IOException
{
int off = 0;
while (N > 0) {
int n = in.read(bb, off, N);
if (n == -1)
return false;
N = N - n;
off += n;
}
return true;
}
int off = 0;
byte[] bb;
private char[] readCharArray() {
// first 2 bytes are the number of "chars" stored in this table
int size = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
char [] cc = new char[size];
for (int i = 0; i < size; i++) {
cc[i] = (char)(((bb[off++]&0xff)<<8) | (bb[off++]&0xff));
}
return cc;
}
void readSINGLEBYTE() {
char[] map = readCharArray();
for (int i = 0; i < map.length; i++) {
char c = map[i];
if (c != UNMAPPABLE_DECODING) {
c2b[c2bIndex[c >> 8] + (c&0xff)] = (char)i;
}
}
b2cSB = map;
}
void readINDEXC2B() {
char[] map = readCharArray();
for (int i = map.length - 1; i >= 0; i--) {
if (c2b == null && map[i] != -1) {
c2b = new char[map[i] + 256];
Arrays.fill(c2b, (char)UNMAPPABLE_ENCODING);
break;
}
}
c2bIndex = map;
}
char[] readDB(int b1Min, int b2Min, int segSize) {
char[] map = readCharArray();
for (int i = 0; i < map.length; i++) {
char c = map[i];
if (c != UNMAPPABLE_DECODING) {
int b1 = i / segSize;
int b2 = i % segSize;
int b = (b1 + b1Min)* 256 + (b2 + b2Min);
//System.out.printf(" DB %x\t%x%n", b, c & 0xffff);
c2b[c2bIndex[c >> 8] + (c&0xff)] = (char)(b);
}
}
return map;
}
void readDOUBLEBYTE1() {
b1MinDB1 = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
b1MaxDB1 = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
b2Min = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
b2Max = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
dbSegSize = b2Max - b2Min + 1;
b2cDB1 = readDB(b1MinDB1, b2Min, dbSegSize);
}
void readDOUBLEBYTE2() {
b1MinDB2 = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
b1MaxDB2 = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
b2Min = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
b2Max = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
dbSegSize = b2Max - b2Min + 1;
b2cDB2 = readDB(b1MinDB2, b2Min, dbSegSize);
}
void readCOMPOSITE() {
char[] map = readCharArray();
int mLen = map.length/3;
b2cComp = new Entry[mLen];
c2bComp = new Entry[mLen];
for (int i = 0, j= 0; i < mLen; i++) {
Entry m = new Entry();
m.bs = map[j++];
m.cp = map[j++];
m.cp2 = map[j++];
b2cComp[i] = m;
c2bComp[i] = m;
}
Arrays.sort(c2bComp, 0, c2bComp.length, comparatorComp);
}
CharsetMapping load(InputStream in) {
try {
// The first 4 bytes are the size of the total data followed in
// this .dat file.
int len = ((in.read()&0xff) << 24) | ((in.read()&0xff) << 16) |
((in.read()&0xff) << 8) | (in.read()&0xff);
bb = new byte[len];
off = 0;
//System.out.printf("In : Total=%d%n", len);
// Read in all bytes
if (!readNBytes(in, bb, len))
throw new RuntimeException("Corrupted data file");
in.close();
while (off < len) {
int type = ((bb[off++]&0xff)<<8) | (bb[off++]&0xff);
switch(type) {
case MAP_INDEXC2B:
readINDEXC2B();
break;
case MAP_SINGLEBYTE:
readSINGLEBYTE();
break;
case MAP_DOUBLEBYTE1:
readDOUBLEBYTE1();
break;
case MAP_DOUBLEBYTE2:
readDOUBLEBYTE2();
break;
case MAP_SUPPLEMENT:
b2cSupp = readCharArray();
break;
case MAP_SUPPLEMENT_C2B:
c2bSupp = readCharArray();
break;
case MAP_COMPOSITE:
readCOMPOSITE();
break;
default:
throw new RuntimeException("Corrupted data file");
}
}
bb = null;
return this;
} catch (IOException x) {
x.printStackTrace();
return null;
}
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2004, 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.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CoderResult;
/**
* A decoder that can be delegated to by another decoder
* when normal inheritance cannot be used.
* Used by autodecting decoders.
*/
public interface DelegatableDecoder {
CoderResult decodeLoop(ByteBuffer src, CharBuffer dst);
void implReset();
CoderResult implFlush(CharBuffer out);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,161 @@
/*
* Copyright (c) 2004, 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.nio.charset.Charset;
import java.nio.charset.spi.CharsetProvider;
import java.util.Iterator;
import java.util.Map;
/**
* Abstract base class for fast charset providers.
*
* @author Mark Reinhold
*/
public class FastCharsetProvider
extends CharsetProvider
{
// Maps canonical names to class names
private Map<String,String> classMap;
// Maps alias names to canonical names
private Map<String,String> aliasMap;
// Maps canonical names to cached instances
private Map<String,Charset> cache;
private String packagePrefix;
protected FastCharsetProvider(String pp,
Map<String,String> am,
Map<String,String> cm,
Map<String,Charset> c)
{
packagePrefix = pp;
aliasMap = am;
classMap = cm;
cache = c;
}
private String canonicalize(String csn) {
String acn = aliasMap.get(csn);
return (acn != null) ? acn : csn;
}
// Private ASCII-only version, optimized for interpretation during startup
//
private static String toLower(String s) {
int n = s.length();
boolean allLower = true;
for (int i = 0; i < n; i++) {
int c = s.charAt(i);
if (((c - 'A') | ('Z' - c)) >= 0) {
allLower = false;
break;
}
}
if (allLower)
return s;
char[] ca = new char[n];
for (int i = 0; i < n; i++) {
int c = s.charAt(i);
if (((c - 'A') | ('Z' - c)) >= 0)
ca[i] = (char)(c + 0x20);
else
ca[i] = (char)c;
}
return new String(ca);
}
private Charset lookup(String charsetName) {
String csn = canonicalize(toLower(charsetName));
// Check cache first
Charset cs = cache.get(csn);
if (cs != null)
return cs;
// Do we even support this charset?
String cln = classMap.get(csn);
if (cln == null)
return null;
if (cln.equals("US_ASCII")) {
cs = new US_ASCII();
cache.put(csn, cs);
return cs;
}
// Instantiate the charset and cache it
try {
@SuppressWarnings("deprecation")
Object o= Class.forName(packagePrefix + "." + cln,
true,
this.getClass().getClassLoader()).newInstance();
cs = (Charset)o;
cache.put(csn, cs);
return cs;
} catch (ClassNotFoundException |
IllegalAccessException |
InstantiationException x) {
return null;
}
}
public final Charset charsetForName(String charsetName) {
synchronized (this) {
return lookup(canonicalize(charsetName));
}
}
public final Iterator<Charset> charsets() {
return new Iterator<Charset>() {
Iterator<String> i = classMap.keySet().iterator();
public boolean hasNext() {
return i.hasNext();
}
public Charset next() {
String csn = i.next();
return lookup(csn);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}

View file

@ -0,0 +1,462 @@
/*
* Copyright (c) 2010, 2013, 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.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.Arrays;
import sun.nio.cs.DoubleByte;
import sun.nio.cs.Surrogate;
import static sun.nio.cs.CharsetMapping.*;
public class HKSCS {
public static class Decoder extends DoubleByte.Decoder {
static int b2Min = 0x40;
static int b2Max = 0xfe;
private char[][] b2cBmp;
private char[][] b2cSupp;
private DoubleByte.Decoder big5Dec;
protected Decoder(Charset cs,
DoubleByte.Decoder big5Dec,
char[][] b2cBmp, char[][] b2cSupp)
{
// super(cs, 0.5f, 1.0f);
// need to extends DoubleByte.Decoder so the
// sun.io can use it. this implementation
super(cs, 0.5f, 1.0f, null, null, 0, 0, true);
this.big5Dec = big5Dec;
this.b2cBmp = b2cBmp;
this.b2cSupp = b2cSupp;
}
public char decodeSingle(int b) {
return big5Dec.decodeSingle(b);
}
public char decodeBig5(int b1, int b2) {
return big5Dec.decodeDouble(b1, b2);
}
public char decodeDouble(int b1, int b2) {
return b2cBmp[b1][b2 - b2Min];
}
public char decodeDoubleEx(int b1, int b2) {
/* if the b2cSupp is null, the subclass need
to override the methold
if (b2cSupp == null)
return UNMAPPABLE_DECODING;
*/
return b2cSupp[b1][b2 - b2Min];
}
protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
try {
while (sp < sl) {
int b1 = sa[sp] & 0xff;
char c = decodeSingle(b1);
int inSize = 1, outSize = 1;
char[] cc = null;
if (c == UNMAPPABLE_DECODING) {
if (sl - sp < 2)
return CoderResult.UNDERFLOW;
int b2 = sa[sp + 1] & 0xff;
inSize++;
if (b2 < b2Min || b2 > b2Max)
return CoderResult.unmappableForLength(2);
c = decodeDouble(b1, b2); //bmp
if (c == UNMAPPABLE_DECODING) {
c = decodeDoubleEx(b1, b2); //supp
if (c == UNMAPPABLE_DECODING) {
c = decodeBig5(b1, b2); //big5
if (c == UNMAPPABLE_DECODING)
return CoderResult.unmappableForLength(2);
} else {
// supplementary character in u+2xxxx area
outSize = 2;
}
}
}
if (dl - dp < outSize)
return CoderResult.OVERFLOW;
if (outSize == 2) {
// supplementary characters
da[dp++] = Surrogate.high(0x20000 + c);
da[dp++] = Surrogate.low(0x20000 + c);
} else {
da[dp++] = c;
}
sp += inSize;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
int mark = src.position();
try {
while (src.hasRemaining()) {
char[] cc = null;
int b1 = src.get() & 0xff;
int inSize = 1, outSize = 1;
char c = decodeSingle(b1);
if (c == UNMAPPABLE_DECODING) {
if (src.remaining() < 1)
return CoderResult.UNDERFLOW;
int b2 = src.get() & 0xff;
inSize++;
if (b2 < b2Min || b2 > b2Max)
return CoderResult.unmappableForLength(2);
c = decodeDouble(b1, b2); //bmp
if (c == UNMAPPABLE_DECODING) {
c = decodeDoubleEx(b1, b2); //supp
if (c == UNMAPPABLE_DECODING) {
c = decodeBig5(b1, b2); //big5
if (c == UNMAPPABLE_DECODING)
return CoderResult.unmappableForLength(2);
} else {
outSize = 2;
}
}
}
if (dst.remaining() < outSize)
return CoderResult.OVERFLOW;
if (outSize == 2) {
dst.put(Surrogate.high(0x20000 + c));
dst.put(Surrogate.low(0x20000 + c));
} else {
dst.put(c);
}
mark += inSize;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
public int decode(byte[] src, int sp, int len, char[] dst) {
int dp = 0;
int sl = sp + len;
char repl = replacement().charAt(0);
while (sp < sl) {
int b1 = src[sp++] & 0xff;
char c = decodeSingle(b1);
if (c == UNMAPPABLE_DECODING) {
if (sl == sp) {
c = repl;
} else {
int b2 = src[sp++] & 0xff;
if (b2 < b2Min || b2 > b2Max) {
c = repl;
} else if ((c = decodeDouble(b1, b2)) == UNMAPPABLE_DECODING) {
c = decodeDoubleEx(b1, b2); //supp
if (c == UNMAPPABLE_DECODING) {
c = decodeBig5(b1, b2); //big5
if (c == UNMAPPABLE_DECODING)
c = repl;
} else {
// supplementary character in u+2xxxx area
dst[dp++] = Surrogate.high(0x20000 + c);
dst[dp++] = Surrogate.low(0x20000 + c);
continue;
}
}
}
}
dst[dp++] = c;
}
return dp;
}
public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
if (src.hasArray() && dst.hasArray())
return decodeArrayLoop(src, dst);
else
return decodeBufferLoop(src, dst);
}
public static void initb2c(char[][]b2c, String[] b2cStr)
{
for (int i = 0; i < b2cStr.length; i++) {
if (b2cStr[i] == null)
b2c[i] = DoubleByte.B2C_UNMAPPABLE;
else
b2c[i] = b2cStr[i].toCharArray();
}
}
}
public static class Encoder extends DoubleByte.Encoder {
private DoubleByte.Encoder big5Enc;
private char[][] c2bBmp;
private char[][] c2bSupp;
protected Encoder(Charset cs,
DoubleByte.Encoder big5Enc,
char[][] c2bBmp,
char[][] c2bSupp)
{
super(cs, null, null, true);
this.big5Enc = big5Enc;
this.c2bBmp = c2bBmp;
this.c2bSupp = c2bSupp;
}
public int encodeBig5(char ch) {
return big5Enc.encodeChar(ch);
}
public int encodeChar(char ch) {
int bb = c2bBmp[ch >> 8][ch & 0xff];
if (bb == UNMAPPABLE_ENCODING)
return encodeBig5(ch);
return bb;
}
public int encodeSupp(int cp) {
if ((cp & 0xf0000) != 0x20000)
return UNMAPPABLE_ENCODING;
return c2bSupp[(cp >> 8) & 0xff][cp & 0xff];
}
public boolean canEncode(char c) {
return encodeChar(c) != UNMAPPABLE_ENCODING;
}
protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
try {
while (sp < sl) {
char c = sa[sp];
int inSize = 1;
int bb = encodeChar(c);
if (bb == UNMAPPABLE_ENCODING) {
if (Character.isSurrogate(c)) {
int cp;
if ((cp = sgp().parse(c, sa, sp, sl)) < 0)
return sgp.error();
bb = encodeSupp(cp);
if (bb == UNMAPPABLE_ENCODING)
return CoderResult.unmappableForLength(2);
inSize = 2;
} else {
return CoderResult.unmappableForLength(1);
}
}
if (bb > MAX_SINGLEBYTE) { // DoubleByte
if (dl - dp < 2)
return CoderResult.OVERFLOW;
da[dp++] = (byte)(bb >> 8);
da[dp++] = (byte)bb;
} else { // SingleByte
if (dl - dp < 1)
return CoderResult.OVERFLOW;
da[dp++] = (byte)bb;
}
sp += inSize;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
int mark = src.position();
try {
while (src.hasRemaining()) {
int inSize = 1;
char c = src.get();
int bb = encodeChar(c);
if (bb == UNMAPPABLE_ENCODING) {
if (Character.isSurrogate(c)) {
int cp;
if ((cp = sgp().parse(c, src)) < 0)
return sgp.error();
bb = encodeSupp(cp);
if (bb == UNMAPPABLE_ENCODING)
return CoderResult.unmappableForLength(2);
inSize = 2;
} else {
return CoderResult.unmappableForLength(1);
}
}
if (bb > MAX_SINGLEBYTE) { // DoubleByte
if (dst.remaining() < 2)
return CoderResult.OVERFLOW;
dst.put((byte)(bb >> 8));
dst.put((byte)(bb));
} else {
if (dst.remaining() < 1)
return CoderResult.OVERFLOW;
dst.put((byte)bb);
}
mark += inSize;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
if (src.hasArray() && dst.hasArray())
return encodeArrayLoop(src, dst);
else
return encodeBufferLoop(src, dst);
}
private byte[] repl = replacement();
protected void implReplaceWith(byte[] newReplacement) {
repl = newReplacement;
}
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
while (sp < sl) {
char c = src[sp++];
int bb = encodeChar(c);
if (bb == UNMAPPABLE_ENCODING) {
if (!Character.isHighSurrogate(c) || sp == sl ||
!Character.isLowSurrogate(src[sp]) ||
(bb = encodeSupp(Character.toCodePoint(c, src[sp++])))
== UNMAPPABLE_ENCODING) {
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
continue;
}
}
if (bb > MAX_SINGLEBYTE) { // DoubleByte
dst[dp++] = (byte)(bb >> 8);
dst[dp++] = (byte)bb;
} else { // SingleByte
dst[dp++] = (byte)bb;
}
}
return dp;
}
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + len;
int dl = dst.length;
while (sp < sl) {
char c = StringUTF16.getChar(src, sp++);
int bb = encodeChar(c);
if (bb == UNMAPPABLE_ENCODING) {
if (!Character.isHighSurrogate(c) || sp == sl ||
!Character.isLowSurrogate(StringUTF16.getChar(src,sp)) ||
(bb = encodeSupp(Character.toCodePoint(c, StringUTF16.getChar(src, sp++))))
== UNMAPPABLE_ENCODING) {
dst[dp++] = repl[0];
if (repl.length > 1)
dst[dp++] = repl[1];
continue;
}
}
if (bb > MAX_SINGLEBYTE) { // DoubleByte
dst[dp++] = (byte)(bb >> 8);
dst[dp++] = (byte)bb;
} else { // SingleByte
dst[dp++] = (byte)bb;
}
}
return dp;
}
static char[] C2B_UNMAPPABLE = new char[0x100];
static {
Arrays.fill(C2B_UNMAPPABLE, (char)UNMAPPABLE_ENCODING);
}
public static void initc2b(char[][] c2b, String[] b2cStr, String pua) {
// init c2b/c2bSupp from b2cStr and supp
int b2Min = 0x40;
Arrays.fill(c2b, C2B_UNMAPPABLE);
for (int b1 = 0; b1 < 0x100; b1++) {
String s = b2cStr[b1];
if (s == null)
continue;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == UNMAPPABLE_DECODING)
continue;
int hi = c >> 8;
if (c2b[hi] == C2B_UNMAPPABLE) {
c2b[hi] = new char[0x100];
Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);
}
c2b[hi][c & 0xff] = (char)((b1 << 8) | (i + b2Min));
}
}
if (pua != null) { // add the compatibility pua entries
char c = '\ue000'; //first pua character
for (int i = 0; i < pua.length(); i++) {
char bb = pua.charAt(i);
if (bb != UNMAPPABLE_DECODING) {
int hi = c >> 8;
if (c2b[hi] == C2B_UNMAPPABLE) {
c2b[hi] = new char[0x100];
Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);
}
c2b[hi][c & 0xff] = bb;
}
c++;
}
}
}
}
}

View file

@ -0,0 +1,33 @@
/*
* Copyright (c) 2000, 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;
public interface HistoricallyNamedCharset {
public String historicalName();
}

View file

@ -0,0 +1,309 @@
/*
* Copyright (c) 2000, 2017, 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.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
public class ISO_8859_1
extends Charset
implements HistoricallyNamedCharset
{
public static final ISO_8859_1 INSTANCE = new ISO_8859_1();
public ISO_8859_1() {
super("ISO-8859-1", StandardCharsets.aliases_ISO_8859_1());
}
public String historicalName() {
return "ISO8859_1";
}
public boolean contains(Charset cs) {
return ((cs instanceof US_ASCII)
|| (cs instanceof ISO_8859_1));
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static class Decoder extends CharsetDecoder
implements ArrayDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
try {
while (sp < sl) {
byte b = sa[sp];
if (dp >= dl)
return CoderResult.OVERFLOW;
da[dp++] = (char)(b & 0xff);
sp++;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
private CoderResult decodeBufferLoop(ByteBuffer src,
CharBuffer dst)
{
int mark = src.position();
try {
while (src.hasRemaining()) {
byte b = src.get();
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
dst.put((char)(b & 0xff));
mark++;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult decodeLoop(ByteBuffer src,
CharBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return decodeArrayLoop(src, dst);
else
return decodeBufferLoop(src, dst);
}
public int decode(byte[] src, int sp, int len, char[] dst) {
if (len > dst.length)
len = dst.length;
int dp = 0;
while (dp < len)
dst[dp++] = (char)(src[sp++] & 0xff);
return dp;
}
public boolean isASCIICompatible() {
return true;
}
}
private static class Encoder extends CharsetEncoder
implements ArrayEncoder {
private Encoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
public boolean canEncode(char c) {
return c <= '\u00FF';
}
public boolean isLegalReplacement(byte[] repl) {
return true; // we accept any byte value
}
private final Surrogate.Parser sgp = new Surrogate.Parser();
// Method possible replaced with a compiler intrinsic.
private static int encodeISOArray(char[] sa, int sp,
byte[] da, int dp, int len) {
if (len <= 0) {
return 0;
}
encodeISOArrayCheck(sa, sp, da, dp, len);
return implEncodeISOArray(sa, sp, da, dp, len);
}
@HotSpotIntrinsicCandidate
private static int implEncodeISOArray(char[] sa, int sp,
byte[] da, int dp, int len)
{
int i = 0;
for (; i < len; i++) {
char c = sa[sp++];
if (c > '\u00FF')
break;
da[dp++] = (byte)c;
}
return i;
}
private static void encodeISOArrayCheck(char[] sa, int sp,
byte[] da, int dp, int len) {
Objects.requireNonNull(sa);
Objects.requireNonNull(da);
if (sp < 0 || sp >= sa.length) {
throw new ArrayIndexOutOfBoundsException(sp);
}
if (dp < 0 || dp >= da.length) {
throw new ArrayIndexOutOfBoundsException(dp);
}
int endIndexSP = sp + len - 1;
if (endIndexSP < 0 || endIndexSP >= sa.length) {
throw new ArrayIndexOutOfBoundsException(endIndexSP);
}
int endIndexDP = dp + len - 1;
if (endIndexDP < 0 || endIndexDP >= da.length) {
throw new ArrayIndexOutOfBoundsException(endIndexDP);
}
}
private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst)
{
char[] sa = src.array();
int soff = src.arrayOffset();
int sp = soff + src.position();
int sl = soff + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
byte[] da = dst.array();
int doff = dst.arrayOffset();
int dp = doff + dst.position();
int dl = doff + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
int dlen = dl - dp;
int slen = sl - sp;
int len = (dlen < slen) ? dlen : slen;
try {
int ret = encodeISOArray(sa, sp, da, dp, len);
sp = sp + ret;
dp = dp + ret;
if (ret != len) {
if (sgp.parse(sa[sp], sa, sp, sl) < 0)
return sgp.error();
return sgp.unmappableResult();
}
if (len < slen)
return CoderResult.OVERFLOW;
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - soff);
dst.position(dp - doff);
}
}
private CoderResult encodeBufferLoop(CharBuffer src,
ByteBuffer dst)
{
int mark = src.position();
try {
while (src.hasRemaining()) {
char c = src.get();
if (c <= '\u00FF') {
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
dst.put((byte)c);
mark++;
continue;
}
if (sgp.parse(c, src) < 0)
return sgp.error();
return sgp.unmappableResult();
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult encodeLoop(CharBuffer src,
ByteBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return encodeArrayLoop(src, dst);
else
return encodeBufferLoop(src, dst);
}
private byte repl = (byte)'?';
protected void implReplaceWith(byte[] newReplacement) {
repl = newReplacement[0];
}
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int slen = Math.min(len, dst.length);
int sl = sp + slen;
while (sp < sl) {
int ret = encodeISOArray(src, sp, dst, dp, slen);
sp = sp + ret;
dp = dp + ret;
if (ret != slen) {
char c = src[sp++];
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(src[sp])) {
if (len > dst.length) {
sl++;
len--;
}
sp++;
}
dst[dp++] = repl;
slen = Math.min((sl - sp), (dst.length - dp));
}
}
return dp;
}
public boolean isASCIICompatible() {
return true;
}
}
}

View file

@ -0,0 +1,354 @@
/*
* Copyright (c) 2008, 2012, 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.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.Arrays;
import static sun.nio.cs.CharsetMapping.*;
public class SingleByte
{
private static final CoderResult withResult(CoderResult cr,
Buffer src, int sp,
Buffer dst, int dp)
{
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
return cr;
}
public static final class Decoder extends CharsetDecoder
implements ArrayDecoder {
private final char[] b2c;
private final boolean isASCIICompatible;
public Decoder(Charset cs, char[] b2c) {
super(cs, 1.0f, 1.0f);
this.b2c = b2c;
this.isASCIICompatible = false;
}
public Decoder(Charset cs, char[] b2c, boolean isASCIICompatible) {
super(cs, 1.0f, 1.0f);
this.b2c = b2c;
this.isASCIICompatible = isASCIICompatible;
}
private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
CoderResult cr = CoderResult.UNDERFLOW;
if ((dl - dp) < (sl - sp)) {
sl = sp + (dl - dp);
cr = CoderResult.OVERFLOW;
}
while (sp < sl) {
char c = decode(sa[sp]);
if (c == UNMAPPABLE_DECODING) {
return withResult(CoderResult.unmappableForLength(1),
src, sp, dst, dp);
}
da[dp++] = c;
sp++;
}
return withResult(cr, src, sp, dst, dp);
}
private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
int mark = src.position();
try {
while (src.hasRemaining()) {
char c = decode(src.get());
if (c == UNMAPPABLE_DECODING)
return CoderResult.unmappableForLength(1);
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
dst.put(c);
mark++;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
if (src.hasArray() && dst.hasArray())
return decodeArrayLoop(src, dst);
else
return decodeBufferLoop(src, dst);
}
public final char decode(int b) {
return b2c[b + 128];
}
private char repl = '\uFFFD';
protected void implReplaceWith(String newReplacement) {
repl = newReplacement.charAt(0);
}
@Override
public int decode(byte[] src, int sp, int len, char[] dst) {
if (len > dst.length)
len = dst.length;
int dp = 0;
while (dp < len) {
dst[dp] = decode(src[sp++]);
if (dst[dp] == UNMAPPABLE_DECODING) {
dst[dp] = repl;
}
dp++;
}
return dp;
}
@Override
public boolean isASCIICompatible() {
return isASCIICompatible;
}
}
public static final class Encoder extends CharsetEncoder
implements ArrayEncoder {
private Surrogate.Parser sgp;
private final char[] c2b;
private final char[] c2bIndex;
private final boolean isASCIICompatible;
public Encoder(Charset cs, char[] c2b, char[] c2bIndex, boolean isASCIICompatible) {
super(cs, 1.0f, 1.0f);
this.c2b = c2b;
this.c2bIndex = c2bIndex;
this.isASCIICompatible = isASCIICompatible;
}
public boolean canEncode(char c) {
return encode(c) != UNMAPPABLE_ENCODING;
}
public boolean isLegalReplacement(byte[] repl) {
return ((repl.length == 1 && repl[0] == (byte)'?') ||
super.isLegalReplacement(repl));
}
private CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int len = Math.min(dl - dp, sl - sp);
while (len-- > 0) {
char c = sa[sp];
int b = encode(c);
if (b == UNMAPPABLE_ENCODING) {
if (Character.isSurrogate(c)) {
if (sgp == null)
sgp = new Surrogate.Parser();
if (sgp.parse(c, sa, sp, sl) < 0) {
return withResult(sgp.error(), src, sp, dst, dp);
}
return withResult(sgp.unmappableResult(), src, sp, dst, dp);
}
return withResult(CoderResult.unmappableForLength(1),
src, sp, dst, dp);
}
da[dp++] = (byte)b;
sp++;
}
return withResult(sp < sl ? CoderResult.OVERFLOW : CoderResult.UNDERFLOW,
src, sp, dst, dp);
}
private CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
int mark = src.position();
try {
while (src.hasRemaining()) {
char c = src.get();
int b = encode(c);
if (b == UNMAPPABLE_ENCODING) {
if (Character.isSurrogate(c)) {
if (sgp == null)
sgp = new Surrogate.Parser();
if (sgp.parse(c, src) < 0)
return sgp.error();
return sgp.unmappableResult();
}
return CoderResult.unmappableForLength(1);
}
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
dst.put((byte)b);
mark++;
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
if (src.hasArray() && dst.hasArray())
return encodeArrayLoop(src, dst);
else
return encodeBufferLoop(src, dst);
}
public final int encode(char ch) {
char index = c2bIndex[ch >> 8];
if (index == UNMAPPABLE_ENCODING)
return UNMAPPABLE_ENCODING;
return c2b[index + (ch & 0xff)];
}
private byte repl = (byte)'?';
protected void implReplaceWith(byte[] newReplacement) {
repl = newReplacement[0];
}
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = src[sp++];
int b = encode(c);
if (b != UNMAPPABLE_ENCODING) {
dst[dp++] = (byte)b;
continue;
}
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(src[sp])) {
if (len > dst.length) {
sl++;
len--;
}
sp++;
}
dst[dp++] = repl;
}
return dp;
}
@Override
public int encodeFromLatin1(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = (char)(src[sp++] & 0xff);
int b = encode(c);
if (b == UNMAPPABLE_ENCODING) {
dst[dp++] = repl;
} else {
dst[dp++] = (byte)b;
}
}
return dp;
}
@Override
public int encodeFromUTF16(byte[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = StringUTF16.getChar(src, sp++);
int b = encode(c);
if (b != UNMAPPABLE_ENCODING) {
dst[dp++] = (byte)b;
continue;
}
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(StringUTF16.getChar(src, sp))) {
if (len > dst.length) {
sl++;
len--;
}
sp++;
}
dst[dp++] = repl;
}
return dp;
}
@Override
public boolean isASCIICompatible() {
return isASCIICompatible;
}
}
// init the c2b and c2bIndex tables from b2c.
public static void initC2B(char[] b2c, char[] c2bNR,
char[] c2b, char[] c2bIndex) {
for (int i = 0; i < c2bIndex.length; i++)
c2bIndex[i] = UNMAPPABLE_ENCODING;
for (int i = 0; i < c2b.length; i++)
c2b[i] = UNMAPPABLE_ENCODING;
int off = 0;
for (int i = 0; i < b2c.length; i++) {
char c = b2c[i];
if (c == UNMAPPABLE_DECODING)
continue;
int index = (c >> 8);
if (c2bIndex[index] == UNMAPPABLE_ENCODING) {
c2bIndex[index] = (char)off;
off += 0x100;
}
index = c2bIndex[index] + (c & 0xff);
c2b[index] = (char)((i>=0x80)?(i-0x80):(i+0x80));
}
if (c2bNR != null) {
// c-->b nr entries
int i = 0;
while (i < c2bNR.length) {
char b = c2bNR[i++];
char c = c2bNR[i++];
int index = (c >> 8);
if (c2bIndex[index] == UNMAPPABLE_ENCODING) {
c2bIndex[index] = (char)off;
off += 0x100;
}
index = c2bIndex[index] + (c & 0xff);
c2b[index] = b;
}
}
}
}

View file

@ -0,0 +1,247 @@
/*
* Copyright (c) 2000, 2017, 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.
*
*/
// -- This file was mechanically generated: Do not edit! -- //
package sun.nio.cs;
import java.nio.charset.Charset;
import java.nio.charset.spi.CharsetProvider;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import jdk.internal.vm.annotation.Stable;
import sun.security.action.GetPropertyAction;
public class StandardCharsets extends CharsetProvider {
_INCLUDE_ALIASES_TABLES_
_INCLUDE_ALIASES_MAP_
_INCLUDE_CLASSES_MAP_
_INCLUDE_CACHE_MAP_
// Maps canonical names to class names
private @Stable Map<String,String> classMap;
// Maps alias names to canonical names
private @Stable Map<String,String> aliasMap;
// Maps canonical names to cached instances
private @Stable Map<String,Charset> cache;
private static final String packagePrefix = "sun.nio.cs.";
public StandardCharsets() {
}
private String canonicalize(String csn) {
String acn = aliasMap().get(csn);
return (acn != null) ? acn : csn;
}
private Map<String,String> aliasMap() {
Map<String,String> map = aliasMap;
if (map == null) {
aliasMap = map = new Aliases();
}
return map;
}
private Map<String,String> classMap() {
Map<String,String> map = classMap;
if (map == null) {
classMap = map = new Classes();
}
return map;
}
private Map<String,Charset> cache() {
Map<String,Charset> map = cache;
if (map == null) {
map = new Cache();
map.put("utf-8", UTF_8.INSTANCE);
map.put("iso-8859-1", ISO_8859_1.INSTANCE);
map.put("us-ascii", US_ASCII.INSTANCE);
cache = map;
}
return map;
}
// Private ASCII-only version, optimized for interpretation during startup
//
private static String toLower(String s) {
int n = s.length();
boolean allLower = true;
for (int i = 0; i < n; i++) {
int c = s.charAt(i);
if (((c - 'A') | ('Z' - c)) >= 0) {
allLower = false;
break;
}
}
if (allLower)
return s;
StringBuilder sb = new StringBuilder(n);
for (int i = 0; i < n; i++) {
int c = s.charAt(i);
if (((c - 'A') | ('Z' - c)) >= 0)
sb.append((char)(c + 0x20));
else
sb.append((char)c);
}
return sb.toString();
}
private Charset lookup(String charsetName) {
init();
// By checking these built-ins we can avoid initializing Aliases and
// Classes eagerly during bootstrap
String csn;
if (charsetName.equals("UTF-8")) {
return UTF_8.INSTANCE;
} else if (charsetName.equals("US-ASCII")) {
return US_ASCII.INSTANCE;
} else if (charsetName.equals("ISO-8859-1")) {
return ISO_8859_1.INSTANCE;
} else {
csn = canonicalize(toLower(charsetName));
}
// Check cache first
Charset cs = cache().get(csn);
if (cs != null)
return cs;
// Do we even support this charset?
String cln = classMap().get(csn);
if (cln == null)
return null;
// Instantiate the charset and cache it
try {
@SuppressWarnings("deprecation")
Object o = Class.forName(packagePrefix + cln,
true,
this.getClass().getClassLoader()).newInstance();
return cache(csn, (Charset)o);
} catch (ClassNotFoundException |
IllegalAccessException |
InstantiationException x) {
return null;
}
}
private Charset cache(String csn, Charset cs) {
cache().put(csn, cs);
return cs;
}
public final Charset charsetForName(String charsetName) {
synchronized (this) {
return lookup(charsetName);
}
}
public final Iterator<Charset> charsets() {
Set<String> charsetNames;
synchronized (this) {
init();
// Ensure initialized in synchronized block
charsetNames = classMap().keySet();
aliasMap();
cache();
}
return new Iterator<Charset>() {
Iterator<String> i = charsetNames.iterator();
public boolean hasNext() {
return i.hasNext();
}
public Charset next() {
String csn = i.next();
return lookup(csn);
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
private boolean initialized = false;
/* provider the sun.nio.cs.map property fir sjis/ms932 mapping hack
*/
private void init() {
if (initialized)
return;
if (!jdk.internal.misc.VM.isBooted())
return;
initialized = true;
String map = GetPropertyAction.privilegedGetProperty("sun.nio.cs.map");
if (map != null) {
Map<String,String> aliasMap = aliasMap();
Map<String,String> classMap = classMap();
String[] maps = map.split(",");
for (int i = 0; i < maps.length; i++) {
if (maps[i].equalsIgnoreCase("Windows-31J/Shift_JIS")) {
// if we dont have both sjis and ms932, do nothing
if (classMap.get("shift_jis") == null ||
classMap.get("windows-31j") == null) {
break;
}
aliases_MS932 = new String[] {
"MS932", // JDK historical
"windows-932",
"csWindows31J",
"shift-jis",
"ms_kanji",
"x-sjis",
"csShiftJIS",
// This alias takes precedence over the actual
// Shift_JIS charset itself since aliases are always
// resolved first, before looking up canonical names.
"shift_jis"
};
aliases_SJIS = new String[] { "sjis" };
for (String alias : aliases_MS932) {
aliasMap.put(toLower(alias), "windows-31j");
}
cache().put("shift_jis", null);
break;
}
}
}
}
}

View 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();
}
}

View file

@ -0,0 +1,353 @@
/*
* Copyright (c) 2001, 2005, 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 StreamEncoder extends Writer
{
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");
}
// Factories for java.io.OutputStreamWriter
public static StreamEncoder forOutputStreamWriter(OutputStream out,
Object lock,
String charsetName)
throws UnsupportedEncodingException
{
String csn = charsetName;
if (csn == null)
csn = Charset.defaultCharset().name();
try {
if (Charset.isSupported(csn))
return new StreamEncoder(out, lock, Charset.forName(csn));
} catch (IllegalCharsetNameException x) { }
throw new UnsupportedEncodingException (csn);
}
public static StreamEncoder forOutputStreamWriter(OutputStream out,
Object lock,
Charset cs)
{
return new StreamEncoder(out, lock, cs);
}
public static StreamEncoder forOutputStreamWriter(OutputStream out,
Object lock,
CharsetEncoder enc)
{
return new StreamEncoder(out, lock, enc);
}
// Factory for java.nio.channels.Channels.newWriter
public static StreamEncoder forEncoder(WritableByteChannel ch,
CharsetEncoder enc,
int minBufferCap)
{
return new StreamEncoder(ch, enc, minBufferCap);
}
// -- Public methods corresponding to those in OutputStreamWriter --
// All synchronization and state/argument checking is done in these public
// methods; the concrete stream-encoder subclasses defined below need not
// do any such checking.
public String getEncoding() {
if (isOpen())
return encodingName();
return null;
}
public void flushBuffer() throws IOException {
synchronized (lock) {
if (isOpen())
implFlushBuffer();
else
throw new IOException("Stream closed");
}
}
public void write(int c) throws IOException {
char cbuf[] = new char[1];
cbuf[0] = (char) c;
write(cbuf, 0, 1);
}
public void write(char cbuf[], int off, int len) throws IOException {
synchronized (lock) {
ensureOpen();
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
((off + len) > cbuf.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
implWrite(cbuf, off, len);
}
}
public void write(String str, int off, int len) throws IOException {
/* Check the len before creating a char buffer */
if (len < 0)
throw new IndexOutOfBoundsException();
char cbuf[] = new char[len];
str.getChars(off, off + len, cbuf, 0);
write(cbuf, 0, len);
}
public void write(CharBuffer cb) throws IOException {
int position = cb.position();
try {
synchronized (lock) {
ensureOpen();
implWrite(cb);
}
} finally {
cb.position(position);
}
}
public void flush() throws IOException {
synchronized (lock) {
ensureOpen();
implFlush();
}
}
public void close() throws IOException {
synchronized (lock) {
if (closed)
return;
implClose();
closed = true;
}
}
private boolean isOpen() {
return !closed;
}
// -- Charset-based stream encoder impl --
private Charset cs;
private CharsetEncoder encoder;
private ByteBuffer bb;
// Exactly one of these is non-null
private final OutputStream out;
private WritableByteChannel ch;
// Leftover first char in a surrogate pair
private boolean haveLeftoverChar = false;
private char leftoverChar;
private CharBuffer lcb = null;
private StreamEncoder(OutputStream out, Object lock, Charset cs) {
this(out, lock,
cs.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE));
}
private StreamEncoder(OutputStream out, Object lock, CharsetEncoder enc) {
super(lock);
this.out = out;
this.ch = null;
this.cs = enc.charset();
this.encoder = enc;
// This path disabled until direct buffers are faster
if (false && out instanceof FileOutputStream) {
ch = ((FileOutputStream)out).getChannel();
if (ch != null)
bb = ByteBuffer.allocateDirect(DEFAULT_BYTE_BUFFER_SIZE);
}
if (ch == null) {
bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
}
}
private StreamEncoder(WritableByteChannel ch, CharsetEncoder enc, int mbc) {
this.out = null;
this.ch = ch;
this.cs = enc.charset();
this.encoder = enc;
this.bb = ByteBuffer.allocate(mbc < 0
? DEFAULT_BYTE_BUFFER_SIZE
: mbc);
}
private void writeBytes() throws IOException {
bb.flip();
int lim = bb.limit();
int pos = bb.position();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
if (rem > 0) {
if (ch != null) {
if (ch.write(bb) != rem)
assert false : rem;
} else {
out.write(bb.array(), bb.arrayOffset() + pos, rem);
}
}
bb.clear();
}
private void flushLeftoverChar(CharBuffer cb, boolean endOfInput)
throws IOException
{
if (!haveLeftoverChar && !endOfInput)
return;
if (lcb == null)
lcb = CharBuffer.allocate(2);
else
lcb.clear();
if (haveLeftoverChar)
lcb.put(leftoverChar);
if ((cb != null) && cb.hasRemaining())
lcb.put(cb.get());
lcb.flip();
while (lcb.hasRemaining() || endOfInput) {
CoderResult cr = encoder.encode(lcb, bb, endOfInput);
if (cr.isUnderflow()) {
if (lcb.hasRemaining()) {
leftoverChar = lcb.get();
if (cb != null && cb.hasRemaining()) {
lcb.clear();
lcb.put(leftoverChar).put(cb.get()).flip();
continue;
}
return;
}
break;
}
if (cr.isOverflow()) {
assert bb.position() > 0;
writeBytes();
continue;
}
cr.throwException();
}
haveLeftoverChar = false;
}
void implWrite(char cbuf[], int off, int len)
throws IOException
{
CharBuffer cb = CharBuffer.wrap(cbuf, off, len);
implWrite(cb);
}
void implWrite(CharBuffer cb)
throws IOException
{
if (haveLeftoverChar) {
flushLeftoverChar(cb, false);
}
while (cb.hasRemaining()) {
CoderResult cr = encoder.encode(cb, bb, false);
if (cr.isUnderflow()) {
assert (cb.remaining() <= 1) : cb.remaining();
if (cb.remaining() == 1) {
haveLeftoverChar = true;
leftoverChar = cb.get();
}
break;
}
if (cr.isOverflow()) {
assert bb.position() > 0;
writeBytes();
continue;
}
cr.throwException();
}
}
void implFlushBuffer() throws IOException {
if (bb.position() > 0)
writeBytes();
}
void implFlush() throws IOException {
implFlushBuffer();
if (out != null)
out.flush();
}
void implClose() throws IOException {
flushLeftoverChar(null, true);
try {
for (;;) {
CoderResult cr = encoder.flush(bb);
if (cr.isUnderflow())
break;
if (cr.isOverflow()) {
assert bb.position() > 0;
writeBytes();
continue;
}
cr.throwException();
}
if (bb.position() > 0)
writeBytes();
if (ch != null)
ch.close();
else
out.close();
} catch (IOException x) {
encoder.reset();
throw x;
}
}
String encodingName() {
return ((cs instanceof HistoricallyNamedCharset)
? ((HistoricallyNamedCharset)cs).historicalName()
: cs.name());
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2015, 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 static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET;
import static jdk.internal.misc.Unsafe.ARRAY_BYTE_INDEX_SCALE;
class StringUTF16 {
public static char getChar(byte[] val, int index) {
return unsafe.getChar(val,
ARRAY_BYTE_BASE_OFFSET + ARRAY_BYTE_INDEX_SCALE * index * 2L);
}
private static final jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
}

View file

@ -0,0 +1,362 @@
/*
* Copyright (c) 2000, 2010, 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.nio.CharBuffer;
import java.nio.charset.CoderResult;
import java.nio.charset.MalformedInputException;
import java.nio.charset.UnmappableCharacterException;
/**
* Utility class for dealing with surrogates.
*
* @author Mark Reinhold
* @author Martin Buchholz
* @author Ulf Zibis
*/
public class Surrogate {
private Surrogate() { }
// TODO: Deprecate/remove the following redundant definitions
public static final char MIN_HIGH = Character.MIN_HIGH_SURROGATE;
public static final char MAX_HIGH = Character.MAX_HIGH_SURROGATE;
public static final char MIN_LOW = Character.MIN_LOW_SURROGATE;
public static final char MAX_LOW = Character.MAX_LOW_SURROGATE;
public static final char MIN = Character.MIN_SURROGATE;
public static final char MAX = Character.MAX_SURROGATE;
public static final int UCS4_MIN = Character.MIN_SUPPLEMENTARY_CODE_POINT;
public static final int UCS4_MAX = Character.MAX_CODE_POINT;
/**
* Tells whether or not the given value is in the high surrogate range.
* Use of {@link Character#isHighSurrogate} is generally preferred.
*/
public static boolean isHigh(int c) {
return (MIN_HIGH <= c) && (c <= MAX_HIGH);
}
/**
* Tells whether or not the given value is in the low surrogate range.
* Use of {@link Character#isLowSurrogate} is generally preferred.
*/
public static boolean isLow(int c) {
return (MIN_LOW <= c) && (c <= MAX_LOW);
}
/**
* Tells whether or not the given value is in the surrogate range.
* Use of {@link Character#isSurrogate} is generally preferred.
*/
public static boolean is(int c) {
return (MIN <= c) && (c <= MAX);
}
/**
* Tells whether or not the given UCS-4 character must be represented as a
* surrogate pair in UTF-16.
* Use of {@link Character#isSupplementaryCodePoint} is generally preferred.
*/
public static boolean neededFor(int uc) {
return Character.isSupplementaryCodePoint(uc);
}
/**
* Returns the high UTF-16 surrogate for the given supplementary UCS-4 character.
* Use of {@link Character#highSurrogate} is generally preferred.
*/
public static char high(int uc) {
assert Character.isSupplementaryCodePoint(uc);
return Character.highSurrogate(uc);
}
/**
* Returns the low UTF-16 surrogate for the given supplementary UCS-4 character.
* Use of {@link Character#lowSurrogate} is generally preferred.
*/
public static char low(int uc) {
assert Character.isSupplementaryCodePoint(uc);
return Character.lowSurrogate(uc);
}
/**
* Converts the given surrogate pair into a 32-bit UCS-4 character.
* Use of {@link Character#toCodePoint} is generally preferred.
*/
public static int toUCS4(char c, char d) {
assert Character.isHighSurrogate(c) && Character.isLowSurrogate(d);
return Character.toCodePoint(c, d);
}
/**
* Surrogate parsing support. Charset implementations may use instances of
* this class to handle the details of parsing UTF-16 surrogate pairs.
*/
public static class Parser {
public Parser() { }
private int character; // UCS-4
private CoderResult error = CoderResult.UNDERFLOW;
private boolean isPair;
/**
* Returns the UCS-4 character previously parsed.
*/
public int character() {
assert (error == null);
return character;
}
/**
* Tells whether or not the previously-parsed UCS-4 character was
* originally represented by a surrogate pair.
*/
public boolean isPair() {
assert (error == null);
return isPair;
}
/**
* Returns the number of UTF-16 characters consumed by the previous
* parse.
*/
public int increment() {
assert (error == null);
return isPair ? 2 : 1;
}
/**
* If the previous parse operation detected an error, return the object
* describing that error.
*/
public CoderResult error() {
assert (error != null);
return error;
}
/**
* Returns an unmappable-input result object, with the appropriate
* input length, for the previously-parsed character.
*/
public CoderResult unmappableResult() {
assert (error == null);
return CoderResult.unmappableForLength(isPair ? 2 : 1);
}
/**
* Parses a UCS-4 character from the given source buffer, handling
* surrogates.
*
* @param c The first character
* @param in The source buffer, from which one more character
* will be consumed if c is a high surrogate
*
* @return Either a parsed UCS-4 character, in which case the isPair()
* and increment() methods will return meaningful values, or
* -1, in which case error() will return a descriptive result
* object
*/
public int parse(char c, CharBuffer in) {
if (Character.isHighSurrogate(c)) {
if (!in.hasRemaining()) {
error = CoderResult.UNDERFLOW;
return -1;
}
char d = in.get();
if (Character.isLowSurrogate(d)) {
character = Character.toCodePoint(c, d);
isPair = true;
error = null;
return character;
}
error = CoderResult.malformedForLength(1);
return -1;
}
if (Character.isLowSurrogate(c)) {
error = CoderResult.malformedForLength(1);
return -1;
}
character = c;
isPair = false;
error = null;
return character;
}
/**
* Parses a UCS-4 character from the given source buffer, handling
* surrogates.
*
* @param c The first character
* @param ia The input array, from which one more character
* will be consumed if c is a high surrogate
* @param ip The input index
* @param il The input limit
*
* @return Either a parsed UCS-4 character, in which case the isPair()
* and increment() methods will return meaningful values, or
* -1, in which case error() will return a descriptive result
* object
*/
public int parse(char c, char[] ia, int ip, int il) {
assert (ia[ip] == c);
if (Character.isHighSurrogate(c)) {
if (il - ip < 2) {
error = CoderResult.UNDERFLOW;
return -1;
}
char d = ia[ip + 1];
if (Character.isLowSurrogate(d)) {
character = Character.toCodePoint(c, d);
isPair = true;
error = null;
return character;
}
error = CoderResult.malformedForLength(1);
return -1;
}
if (Character.isLowSurrogate(c)) {
error = CoderResult.malformedForLength(1);
return -1;
}
character = c;
isPair = false;
error = null;
return character;
}
}
/**
* Surrogate generation support. Charset implementations may use instances
* of this class to handle the details of generating UTF-16 surrogate
* pairs.
*/
public static class Generator {
public Generator() { }
private CoderResult error = CoderResult.OVERFLOW;
/**
* If the previous generation operation detected an error, return the
* object describing that error.
*/
public CoderResult error() {
assert error != null;
return error;
}
/**
* Generates one or two UTF-16 characters to represent the given UCS-4
* character.
*
* @param uc The UCS-4 character
* @param len The number of input bytes from which the UCS-4 value
* was constructed (used when creating result objects)
* @param dst The destination buffer, to which one or two UTF-16
* characters will be written
*
* @return Either a positive count of the number of UTF-16 characters
* written to the destination buffer, or -1, in which case
* error() will return a descriptive result object
*/
public int generate(int uc, int len, CharBuffer dst) {
if (Character.isBmpCodePoint(uc)) {
char c = (char) uc;
if (Character.isSurrogate(c)) {
error = CoderResult.malformedForLength(len);
return -1;
}
if (dst.remaining() < 1) {
error = CoderResult.OVERFLOW;
return -1;
}
dst.put(c);
error = null;
return 1;
} else if (Character.isValidCodePoint(uc)) {
if (dst.remaining() < 2) {
error = CoderResult.OVERFLOW;
return -1;
}
dst.put(Character.highSurrogate(uc));
dst.put(Character.lowSurrogate(uc));
error = null;
return 2;
} else {
error = CoderResult.unmappableForLength(len);
return -1;
}
}
/**
* Generates one or two UTF-16 characters to represent the given UCS-4
* character.
*
* @param uc The UCS-4 character
* @param len The number of input bytes from which the UCS-4 value
* was constructed (used when creating result objects)
* @param da The destination array, to which one or two UTF-16
* characters will be written
* @param dp The destination position
* @param dl The destination limit
*
* @return Either a positive count of the number of UTF-16 characters
* written to the destination buffer, or -1, in which case
* error() will return a descriptive result object
*/
public int generate(int uc, int len, char[] da, int dp, int dl) {
if (Character.isBmpCodePoint(uc)) {
char c = (char) uc;
if (Character.isSurrogate(c)) {
error = CoderResult.malformedForLength(len);
return -1;
}
if (dl - dp < 1) {
error = CoderResult.OVERFLOW;
return -1;
}
da[dp] = c;
error = null;
return 1;
} else if (Character.isValidCodePoint(uc)) {
if (dl - dp < 2) {
error = CoderResult.OVERFLOW;
return -1;
}
da[dp] = Character.highSurrogate(uc);
da[dp + 1] = Character.lowSurrogate(uc);
error = null;
return 2;
} else {
error = CoderResult.unmappableForLength(len);
return -1;
}
}
}
}

View file

@ -0,0 +1,136 @@
/*
* 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.nio.charset.*;
/**
* Utility class for caching per-thread decoders and encoders.
*/
public class ThreadLocalCoders {
private static final int CACHE_SIZE = 3;
private abstract static class Cache {
// Thread-local reference to array of cached objects, in LRU order
private ThreadLocal<Object[]> cache = new ThreadLocal<>();
private final int size;
Cache(int size) {
this.size = size;
}
abstract Object create(Object name);
private void moveToFront(Object[] oa, int i) {
Object ob = oa[i];
for (int j = i; j > 0; j--)
oa[j] = oa[j - 1];
oa[0] = ob;
}
abstract boolean hasName(Object ob, Object name);
Object forName(Object name) {
Object[] oa = cache.get();
if (oa == null) {
oa = new Object[size];
cache.set(oa);
} else {
for (int i = 0; i < oa.length; i++) {
Object ob = oa[i];
if (ob == null)
continue;
if (hasName(ob, name)) {
if (i > 0)
moveToFront(oa, i);
return ob;
}
}
}
// Create a new object
Object ob = create(name);
oa[oa.length - 1] = ob;
moveToFront(oa, oa.length - 1);
return ob;
}
}
private static Cache decoderCache = new Cache(CACHE_SIZE) {
boolean hasName(Object ob, Object name) {
if (name instanceof String)
return (((CharsetDecoder)ob).charset().name().equals(name));
if (name instanceof Charset)
return ((CharsetDecoder)ob).charset().equals(name);
return false;
}
Object create(Object name) {
if (name instanceof String)
return Charset.forName((String)name).newDecoder();
if (name instanceof Charset)
return ((Charset)name).newDecoder();
assert false;
return null;
}
};
public static CharsetDecoder decoderFor(Object name) {
CharsetDecoder cd = (CharsetDecoder)decoderCache.forName(name);
cd.reset();
return cd;
}
private static Cache encoderCache = new Cache(CACHE_SIZE) {
boolean hasName(Object ob, Object name) {
if (name instanceof String)
return (((CharsetEncoder)ob).charset().name().equals(name));
if (name instanceof Charset)
return ((CharsetEncoder)ob).charset().equals(name);
return false;
}
Object create(Object name) {
if (name instanceof String)
return Charset.forName((String)name).newEncoder();
if (name instanceof Charset)
return ((Charset)name).newEncoder();
assert false;
return null;
}
};
public static CharsetEncoder encoderFor(Object name) {
CharsetEncoder ce = (CharsetEncoder)encoderCache.forName(name);
ce.reset();
return ce;
}
}

View file

@ -0,0 +1,272 @@
/*
* Copyright (c) 2000, 2017, 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.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
public class US_ASCII
extends Charset
implements HistoricallyNamedCharset
{
public static final US_ASCII INSTANCE = new US_ASCII();
public US_ASCII() {
super("US-ASCII", StandardCharsets.aliases_US_ASCII());
}
public String historicalName() {
return "ASCII";
}
public boolean contains(Charset cs) {
return (cs instanceof US_ASCII);
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static class Decoder extends CharsetDecoder
implements ArrayDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
try {
while (sp < sl) {
byte b = sa[sp];
if (b >= 0) {
if (dp >= dl)
return CoderResult.OVERFLOW;
da[dp++] = (char)b;
sp++;
continue;
}
return CoderResult.malformedForLength(1);
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
private CoderResult decodeBufferLoop(ByteBuffer src,
CharBuffer dst)
{
int mark = src.position();
try {
while (src.hasRemaining()) {
byte b = src.get();
if (b >= 0) {
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
dst.put((char)b);
mark++;
continue;
}
return CoderResult.malformedForLength(1);
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult decodeLoop(ByteBuffer src,
CharBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return decodeArrayLoop(src, dst);
else
return decodeBufferLoop(src, dst);
}
private char repl = '\uFFFD';
protected void implReplaceWith(String newReplacement) {
repl = newReplacement.charAt(0);
}
public int decode(byte[] src, int sp, int len, char[] dst) {
int dp = 0;
len = Math.min(len, dst.length);
while (dp < len) {
byte b = src[sp++];
if (b >= 0)
dst[dp++] = (char)b;
else
dst[dp++] = repl;
}
return dp;
}
public boolean isASCIICompatible() {
return true;
}
}
private static class Encoder extends CharsetEncoder
implements ArrayEncoder {
private Encoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
public boolean canEncode(char c) {
return c < 0x80;
}
public boolean isLegalReplacement(byte[] repl) {
return (repl.length == 1 && repl[0] >= 0) ||
super.isLegalReplacement(repl);
}
private final Surrogate.Parser sgp = new Surrogate.Parser();
private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst)
{
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
try {
while (sp < sl) {
char c = sa[sp];
if (c < 0x80) {
if (dp >= dl)
return CoderResult.OVERFLOW;
da[dp] = (byte)c;
sp++; dp++;
continue;
}
if (sgp.parse(c, sa, sp, sl) < 0)
return sgp.error();
return sgp.unmappableResult();
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
private CoderResult encodeBufferLoop(CharBuffer src,
ByteBuffer dst)
{
int mark = src.position();
try {
while (src.hasRemaining()) {
char c = src.get();
if (c < 0x80) {
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
dst.put((byte)c);
mark++;
continue;
}
if (sgp.parse(c, src) < 0)
return sgp.error();
return sgp.unmappableResult();
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected CoderResult encodeLoop(CharBuffer src,
ByteBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return encodeArrayLoop(src, dst);
else
return encodeBufferLoop(src, dst);
}
private byte repl = (byte)'?';
protected void implReplaceWith(byte[] newReplacement) {
repl = newReplacement[0];
}
public int encode(char[] src, int sp, int len, byte[] dst) {
int dp = 0;
int sl = sp + Math.min(len, dst.length);
while (sp < sl) {
char c = src[sp++];
if (c < 0x80) {
dst[dp++] = (byte)c;
continue;
}
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(src[sp])) {
if (len > dst.length) {
sl++;
len--;
}
sp++;
}
dst[dp++] = repl;
}
return dp;
}
public boolean isASCIICompatible() {
return true;
}
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2000, 2005, 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.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
class UTF_16 extends Unicode
{
public UTF_16() {
super("UTF-16", StandardCharsets.aliases_UTF_16());
}
public String historicalName() {
return "UTF-16";
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static class Decoder extends UnicodeDecoder {
public Decoder(Charset cs) {
super(cs, NONE);
}
}
private static class Encoder extends UnicodeEncoder {
public Encoder(Charset cs) {
super(cs, BIG, true);
}
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2000, 2005, 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.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
class UTF_16BE extends Unicode
{
public UTF_16BE() {
super("UTF-16BE", StandardCharsets.aliases_UTF_16BE());
}
public String historicalName() {
return "UnicodeBigUnmarked";
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static class Decoder extends UnicodeDecoder {
public Decoder(Charset cs) {
super(cs, BIG);
}
}
private static class Encoder extends UnicodeEncoder {
public Encoder(Charset cs) {
super(cs, BIG, false);
}
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2000, 2005, 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.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
class UTF_16LE extends Unicode
{
public UTF_16LE() {
super("UTF-16LE", StandardCharsets.aliases_UTF_16LE());
}
public String historicalName() {
return "UnicodeLittleUnmarked";
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static class Decoder extends UnicodeDecoder {
public Decoder(Charset cs) {
super(cs, LITTLE);
}
}
private static class Encoder extends UnicodeEncoder {
public Encoder(Charset cs) {
super(cs, LITTLE, false);
}
}
}

View file

@ -0,0 +1,65 @@
/*
* Copyright (c) 2005, 2006, 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.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
class UTF_16LE_BOM extends Unicode
{
public UTF_16LE_BOM() {
super("x-UTF-16LE-BOM", StandardCharsets.aliases_UTF_16LE_BOM());
}
public String historicalName() {
return "UnicodeLittle";
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
private static class Decoder extends UnicodeDecoder {
public Decoder(Charset cs) {
super(cs, NONE, LITTLE);
}
}
private static class Encoder extends UnicodeEncoder {
public Encoder(Charset cs) {
super(cs, LITTLE, true);
}
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2005, 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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UTF_32 extends Unicode
{
public UTF_32() {
super("UTF-32", StandardCharsets.aliases_UTF_32());
}
public String historicalName() {
return "UTF-32";
}
public CharsetDecoder newDecoder() {
return new UTF_32Coder.Decoder(this, UTF_32Coder.NONE);
}
public CharsetEncoder newEncoder() {
return new UTF_32Coder.Encoder(this, UTF_32Coder.BIG, false);
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2005, 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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UTF_32BE extends Unicode
{
public UTF_32BE() {
super("UTF-32BE", StandardCharsets.aliases_UTF_32BE());
}
public String historicalName() {
return "UTF-32BE";
}
public CharsetDecoder newDecoder() {
return new UTF_32Coder.Decoder(this, UTF_32Coder.BIG);
}
public CharsetEncoder newEncoder() {
return new UTF_32Coder.Encoder(this, UTF_32Coder.BIG, false);
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2005, 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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UTF_32BE_BOM extends Unicode
{
public UTF_32BE_BOM() {
super("X-UTF-32BE-BOM", StandardCharsets.aliases_UTF_32BE_BOM());
}
public String historicalName() {
return "X-UTF-32BE-BOM";
}
public CharsetDecoder newDecoder() {
return new UTF_32Coder.Decoder(this, UTF_32Coder.BIG);
}
public CharsetEncoder newEncoder() {
return new UTF_32Coder.Encoder(this, UTF_32Coder.BIG, true);
}
}

View file

@ -0,0 +1,189 @@
/*
* Copyright (c) 2005, 2010, 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.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CoderResult;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
class UTF_32Coder {
protected static final int BOM_BIG = 0xFEFF;
protected static final int BOM_LITTLE = 0xFFFE0000;
protected static final int NONE = 0;
protected static final int BIG = 1;
protected static final int LITTLE = 2;
protected static class Decoder extends CharsetDecoder {
private int currentBO;
private int expectedBO;
protected Decoder(Charset cs, int bo) {
super(cs, 0.25f, 1.0f);
this.expectedBO = bo;
this.currentBO = NONE;
}
private int getCP(ByteBuffer src) {
return (currentBO==BIG)
?(((src.get() & 0xff) << 24) |
((src.get() & 0xff) << 16) |
((src.get() & 0xff) << 8) |
(src.get() & 0xff))
:((src.get() & 0xff) |
((src.get() & 0xff) << 8) |
((src.get() & 0xff) << 16) |
((src.get() & 0xff) << 24));
}
protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
if (src.remaining() < 4)
return CoderResult.UNDERFLOW;
int mark = src.position();
int cp;
try {
if (currentBO == NONE) {
cp = ((src.get() & 0xff) << 24) |
((src.get() & 0xff) << 16) |
((src.get() & 0xff) << 8) |
(src.get() & 0xff);
if (cp == BOM_BIG && expectedBO != LITTLE) {
currentBO = BIG;
mark += 4;
} else if (cp == BOM_LITTLE && expectedBO != BIG) {
currentBO = LITTLE;
mark += 4;
} else {
if (expectedBO == NONE)
currentBO = BIG;
else
currentBO = expectedBO;
src.position(mark);
}
}
while (src.remaining() >= 4) {
cp = getCP(src);
if (Character.isBmpCodePoint(cp)) {
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
mark += 4;
dst.put((char) cp);
} else if (Character.isValidCodePoint(cp)) {
if (dst.remaining() < 2)
return CoderResult.OVERFLOW;
mark += 4;
dst.put(Character.highSurrogate(cp));
dst.put(Character.lowSurrogate(cp));
} else {
return CoderResult.malformedForLength(4);
}
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected void implReset() {
currentBO = NONE;
}
}
protected static class Encoder extends CharsetEncoder {
private boolean doBOM = false;
private boolean doneBOM = true;
private int byteOrder;
protected void put(int cp, ByteBuffer dst) {
if (byteOrder==BIG) {
dst.put((byte)(cp >> 24));
dst.put((byte)(cp >> 16));
dst.put((byte)(cp >> 8));
dst.put((byte)cp);
} else {
dst.put((byte)cp);
dst.put((byte)(cp >> 8));
dst.put((byte)(cp >> 16));
dst.put((byte)(cp >> 24));
}
}
protected Encoder(Charset cs, int byteOrder, boolean doBOM) {
super(cs, 4.0f,
doBOM?8.0f:4.0f,
(byteOrder==BIG)?new byte[]{(byte)0, (byte)0, (byte)0xff, (byte)0xfd}
:new byte[]{(byte)0xfd, (byte)0xff, (byte)0, (byte)0});
this.byteOrder = byteOrder;
this.doBOM = doBOM;
this.doneBOM = !doBOM;
}
protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
int mark = src.position();
if (!doneBOM && src.hasRemaining()) {
if (dst.remaining() < 4)
return CoderResult.OVERFLOW;
put(BOM_BIG, dst);
doneBOM = true;
}
try {
while (src.hasRemaining()) {
char c = src.get();
if (!Character.isSurrogate(c)) {
if (dst.remaining() < 4)
return CoderResult.OVERFLOW;
mark++;
put(c, dst);
} else if (Character.isHighSurrogate(c)) {
if (!src.hasRemaining())
return CoderResult.UNDERFLOW;
char low = src.get();
if (Character.isLowSurrogate(low)) {
if (dst.remaining() < 4)
return CoderResult.OVERFLOW;
mark += 2;
put(Character.toCodePoint(c, low), dst);
} else {
return CoderResult.malformedForLength(1);
}
} else {
// assert Character.isLowSurrogate(c);
return CoderResult.malformedForLength(1);
}
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected void implReset() {
doneBOM = !doBOM;
}
}
}

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2005, 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.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UTF_32LE extends Unicode
{
public UTF_32LE() {
super("UTF-32LE", StandardCharsets.aliases_UTF_32LE());
}
public String historicalName() {
return "UTF-32LE";
}
public CharsetDecoder newDecoder() {
return new UTF_32Coder.Decoder(this, UTF_32Coder.LITTLE);
}
public CharsetEncoder newEncoder() {
return new UTF_32Coder.Encoder(this, UTF_32Coder.LITTLE, false);
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2005, 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.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UTF_32LE_BOM extends Unicode
{
public UTF_32LE_BOM() {
super("X-UTF-32LE-BOM", StandardCharsets.aliases_UTF_32LE_BOM());
}
public String historicalName() {
return "X-UTF-32LE-BOM";
}
public CharsetDecoder newDecoder() {
return new UTF_32Coder.Decoder(this, UTF_32Coder.LITTLE);
}
public CharsetEncoder newEncoder() {
return new UTF_32Coder.Encoder(this, UTF_32Coder.LITTLE, true);
}
}

View file

@ -0,0 +1,756 @@
/*
* Copyright (c) 2000, 2017, 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.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/* Legal UTF-8 Byte Sequences
*
* # Code Points Bits Bit/Byte pattern
* 1 7 0xxxxxxx
* U+0000..U+007F 00..7F
*
* 2 11 110xxxxx 10xxxxxx
* U+0080..U+07FF C2..DF 80..BF
*
* 3 16 1110xxxx 10xxxxxx 10xxxxxx
* U+0800..U+0FFF E0 A0..BF 80..BF
* U+1000..U+FFFF E1..EF 80..BF 80..BF
*
* 4 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
* U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
* U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
* U+100000..U10FFFF F4 80..8F 80..BF 80..BF
*
*/
public final class UTF_8 extends Unicode {
public static final UTF_8 INSTANCE = new UTF_8();
public UTF_8() {
super("UTF-8", StandardCharsets.aliases_UTF_8());
}
public String historicalName() {
return "UTF8";
}
public CharsetDecoder newDecoder() {
return new Decoder(this);
}
public CharsetEncoder newEncoder() {
return new Encoder(this);
}
static final void updatePositions(Buffer src, int sp,
Buffer dst, int dp) {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
private static class Decoder extends CharsetDecoder
implements ArrayDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
private static boolean isNotContinuation(int b) {
return (b & 0xc0) != 0x80;
}
// [E0] [A0..BF] [80..BF]
// [E1..EF] [80..BF] [80..BF]
private static boolean isMalformed3(int b1, int b2, int b3) {
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
(b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
}
// only used when there is only one byte left in src buffer
private static boolean isMalformed3_2(int b1, int b2) {
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
(b2 & 0xc0) != 0x80;
}
// [F0] [90..BF] [80..BF] [80..BF]
// [F1..F3] [80..BF] [80..BF] [80..BF]
// [F4] [80..8F] [80..BF] [80..BF]
// only check 80-be range here, the [0xf0,0x80...] and [0xf4,0x90-...]
// will be checked by Character.isSupplementaryCodePoint(uc)
private static boolean isMalformed4(int b2, int b3, int b4) {
return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
(b4 & 0xc0) != 0x80;
}
// only used when there is less than 4 bytes left in src buffer.
// both b1 and b2 should be "& 0xff" before passed in.
private static boolean isMalformed4_2(int b1, int b2) {
return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
(b2 & 0xc0) != 0x80;
}
// tests if b1 and b2 are malformed as the first 2 bytes of a
// legal`4-byte utf-8 byte sequence.
// only used when there is less than 4 bytes left in src buffer,
// after isMalformed4_2 has been invoked.
private static boolean isMalformed4_3(int b3) {
return (b3 & 0xc0) != 0x80;
}
private static CoderResult lookupN(ByteBuffer src, int n)
{
for (int i = 1; i < n; i++) {
if (isNotContinuation(src.get()))
return CoderResult.malformedForLength(i);
}
return CoderResult.malformedForLength(n);
}
private static CoderResult malformedN(ByteBuffer src, int nb) {
switch (nb) {
case 1:
case 2: // always 1
return CoderResult.malformedForLength(1);
case 3:
int b1 = src.get();
int b2 = src.get(); // no need to lookup b3
return CoderResult.malformedForLength(
((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
isNotContinuation(b2)) ? 1 : 2);
case 4: // we don't care the speed here
b1 = src.get() & 0xff;
b2 = src.get() & 0xff;
if (b1 > 0xf4 ||
(b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
isNotContinuation(b2))
return CoderResult.malformedForLength(1);
if (isNotContinuation(src.get()))
return CoderResult.malformedForLength(2);
return CoderResult.malformedForLength(3);
default:
assert false;
return null;
}
}
private static CoderResult malformed(ByteBuffer src, int sp,
CharBuffer dst, int dp,
int nb)
{
src.position(sp - src.arrayOffset());
CoderResult cr = malformedN(src, nb);
updatePositions(src, sp, dst, dp);
return cr;
}
private static CoderResult malformed(ByteBuffer src,
int mark, int nb)
{
src.position(mark);
CoderResult cr = malformedN(src, nb);
src.position(mark);
return cr;
}
private static CoderResult malformedForLength(ByteBuffer src,
int sp,
CharBuffer dst,
int dp,
int malformedNB)
{
updatePositions(src, sp, dst, dp);
return CoderResult.malformedForLength(malformedNB);
}
private static CoderResult malformedForLength(ByteBuffer src,
int mark,
int malformedNB)
{
src.position(mark);
return CoderResult.malformedForLength(malformedNB);
}
private static CoderResult xflow(Buffer src, int sp, int sl,
Buffer dst, int dp, int nb) {
updatePositions(src, sp, dst, dp);
return (nb == 0 || sl - sp < nb)
? CoderResult.UNDERFLOW : CoderResult.OVERFLOW;
}
private static CoderResult xflow(Buffer src, int mark, int nb) {
src.position(mark);
return (nb == 0 || src.remaining() < nb)
? CoderResult.UNDERFLOW : CoderResult.OVERFLOW;
}
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
// This method is optimized for ASCII input.
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] >= 0)
da[dp++] = (char) sa[sp++];
while (sp < sl) {
int b1 = sa[sp];
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
if (dp >= dl)
return xflow(src, sp, sl, dst, dp, 1);
da[dp++] = (char) b1;
sp++;
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
// [C2..DF] [80..BF]
if (sl - sp < 2 || dp >= dl)
return xflow(src, sp, sl, dst, dp, 2);
int b2 = sa[sp + 1];
// Now we check the first byte of 2-byte sequence as
// if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0)
// no longer need to check b1 against c1 & c0 for
// malformed as we did in previous version
// (b1 & 0x1e) == 0x0 || (b2 & 0xc0) != 0x80;
// only need to check the second byte b2.
if (isNotContinuation(b2))
return malformedForLength(src, sp, dst, dp, 1);
da[dp++] = (char) (((b1 << 6) ^ b2)
^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0)));
sp += 2;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
int srcRemaining = sl - sp;
if (srcRemaining < 3 || dp >= dl) {
if (srcRemaining > 1 && isMalformed3_2(b1, sa[sp + 1]))
return malformedForLength(src, sp, dst, dp, 1);
return xflow(src, sp, sl, dst, dp, 3);
}
int b2 = sa[sp + 1];
int b3 = sa[sp + 2];
if (isMalformed3(b1, b2, b3))
return malformed(src, sp, dst, dp, 3);
char c = (char)
((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (Character.isSurrogate(c))
return malformedForLength(src, sp, dst, dp, 3);
da[dp++] = c;
sp += 3;
} else if ((b1 >> 3) == -2) {
// 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
int srcRemaining = sl - sp;
if (srcRemaining < 4 || dl - dp < 2) {
b1 &= 0xff;
if (b1 > 0xf4 ||
srcRemaining > 1 && isMalformed4_2(b1, sa[sp + 1] & 0xff))
return malformedForLength(src, sp, dst, dp, 1);
if (srcRemaining > 2 && isMalformed4_3(sa[sp + 2]))
return malformedForLength(src, sp, dst, dp, 2);
return xflow(src, sp, sl, dst, dp, 4);
}
int b2 = sa[sp + 1];
int b3 = sa[sp + 2];
int b4 = sa[sp + 3];
int uc = ((b1 << 18) ^
(b2 << 12) ^
(b3 << 6) ^
(b4 ^
(((byte) 0xF0 << 18) ^
((byte) 0x80 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (isMalformed4(b2, b3, b4) ||
// shortest form check
!Character.isSupplementaryCodePoint(uc)) {
return malformed(src, sp, dst, dp, 4);
}
da[dp++] = Character.highSurrogate(uc);
da[dp++] = Character.lowSurrogate(uc);
sp += 4;
} else
return malformed(src, sp, dst, dp, 1);
}
return xflow(src, sp, sl, dst, dp, 0);
}
private CoderResult decodeBufferLoop(ByteBuffer src,
CharBuffer dst)
{
int mark = src.position();
int limit = src.limit();
while (mark < limit) {
int b1 = src.get();
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
if (dst.remaining() < 1)
return xflow(src, mark, 1); // overflow
dst.put((char) b1);
mark++;
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
if (limit - mark < 2|| dst.remaining() < 1)
return xflow(src, mark, 2);
int b2 = src.get();
if (isNotContinuation(b2))
return malformedForLength(src, mark, 1);
dst.put((char) (((b1 << 6) ^ b2)
^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0))));
mark += 2;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
int srcRemaining = limit - mark;
if (srcRemaining < 3 || dst.remaining() < 1) {
if (srcRemaining > 1 && isMalformed3_2(b1, src.get()))
return malformedForLength(src, mark, 1);
return xflow(src, mark, 3);
}
int b2 = src.get();
int b3 = src.get();
if (isMalformed3(b1, b2, b3))
return malformed(src, mark, 3);
char c = (char)
((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (Character.isSurrogate(c))
return malformedForLength(src, mark, 3);
dst.put(c);
mark += 3;
} else if ((b1 >> 3) == -2) {
// 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
int srcRemaining = limit - mark;
if (srcRemaining < 4 || dst.remaining() < 2) {
b1 &= 0xff;
if (b1 > 0xf4 ||
srcRemaining > 1 && isMalformed4_2(b1, src.get() & 0xff))
return malformedForLength(src, mark, 1);
if (srcRemaining > 2 && isMalformed4_3(src.get()))
return malformedForLength(src, mark, 2);
return xflow(src, mark, 4);
}
int b2 = src.get();
int b3 = src.get();
int b4 = src.get();
int uc = ((b1 << 18) ^
(b2 << 12) ^
(b3 << 6) ^
(b4 ^
(((byte) 0xF0 << 18) ^
((byte) 0x80 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (isMalformed4(b2, b3, b4) ||
// shortest form check
!Character.isSupplementaryCodePoint(uc)) {
return malformed(src, mark, 4);
}
dst.put(Character.highSurrogate(uc));
dst.put(Character.lowSurrogate(uc));
mark += 4;
} else {
return malformed(src, mark, 1);
}
}
return xflow(src, mark, 0);
}
protected CoderResult decodeLoop(ByteBuffer src,
CharBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return decodeArrayLoop(src, dst);
else
return decodeBufferLoop(src, dst);
}
private static ByteBuffer getByteBuffer(ByteBuffer bb, byte[] ba, int sp)
{
if (bb == null)
bb = ByteBuffer.wrap(ba);
bb.position(sp);
return bb;
}
// returns -1 if there is/are malformed byte(s) and the
// "action" for malformed input is not REPLACE.
public int decode(byte[] sa, int sp, int len, char[] da) {
final int sl = sp + len;
int dp = 0;
int dlASCII = Math.min(len, da.length);
ByteBuffer bb = null; // only necessary if malformed
// ASCII only optimized loop
while (dp < dlASCII && sa[sp] >= 0)
da[dp++] = (char) sa[sp++];
while (sp < sl) {
int b1 = sa[sp++];
if (b1 >= 0) {
// 1 byte, 7 bits: 0xxxxxxx
da[dp++] = (char) b1;
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
// 2 bytes, 11 bits: 110xxxxx 10xxxxxx
if (sp < sl) {
int b2 = sa[sp++];
if (isNotContinuation(b2)) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
sp--; // malformedN(bb, 2) always returns 1
} else {
da[dp++] = (char) (((b1 << 6) ^ b2)^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0)));
}
continue;
}
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
return dp;
} else if ((b1 >> 4) == -2) {
// 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
if (sp + 1 < sl) {
int b2 = sa[sp++];
int b3 = sa[sp++];
if (isMalformed3(b1, b2, b3)) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
sp -= 3;
bb = getByteBuffer(bb, sa, sp);
sp += malformedN(bb, 3).length();
} else {
char c = (char)((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (Character.isSurrogate(c)) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
} else {
da[dp++] = c;
}
}
continue;
}
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
if (sp < sl && isMalformed3_2(b1, sa[sp])) {
da[dp++] = replacement().charAt(0);
continue;
}
da[dp++] = replacement().charAt(0);
return dp;
} else if ((b1 >> 3) == -2) {
// 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
if (sp + 2 < sl) {
int b2 = sa[sp++];
int b3 = sa[sp++];
int b4 = sa[sp++];
int uc = ((b1 << 18) ^
(b2 << 12) ^
(b3 << 6) ^
(b4 ^
(((byte) 0xF0 << 18) ^
((byte) 0x80 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (isMalformed4(b2, b3, b4) ||
// shortest form check
!Character.isSupplementaryCodePoint(uc)) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
sp -= 4;
bb = getByteBuffer(bb, sa, sp);
sp += malformedN(bb, 4).length();
} else {
da[dp++] = Character.highSurrogate(uc);
da[dp++] = Character.lowSurrogate(uc);
}
continue;
}
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
b1 &= 0xff;
if (b1 > 0xf4 ||
sp < sl && isMalformed4_2(b1, sa[sp] & 0xff)) {
da[dp++] = replacement().charAt(0);
continue;
}
sp++;
if (sp < sl && isMalformed4_3(sa[sp])) {
da[dp++] = replacement().charAt(0);
continue;
}
da[dp++] = replacement().charAt(0);
return dp;
} else {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = replacement().charAt(0);
}
}
return dp;
}
public boolean isASCIICompatible() {
return true;
}
}
private static final class Encoder extends CharsetEncoder
implements ArrayEncoder {
private Encoder(Charset cs) {
super(cs, 1.1f, 3.0f);
}
public boolean canEncode(char c) {
return !Character.isSurrogate(c);
}
public boolean isLegalReplacement(byte[] repl) {
return ((repl.length == 1 && repl[0] >= 0) ||
super.isLegalReplacement(repl));
}
private static CoderResult overflow(CharBuffer src, int sp,
ByteBuffer dst, int dp) {
updatePositions(src, sp, dst, dp);
return CoderResult.OVERFLOW;
}
private static CoderResult overflow(CharBuffer src, int mark) {
src.position(mark);
return CoderResult.OVERFLOW;
}
private Surrogate.Parser sgp;
private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst)
{
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
while (sp < sl) {
char c = sa[sp];
if (c < 0x80) {
// Have at most seven bits
if (dp >= dl)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
if (dl - dp < 2)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, sa, sp, sl);
if (uc < 0) {
updatePositions(src, sp, dst, dp);
return sgp.error();
}
if (dl - dp < 4)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xf0 | ((uc >> 18)));
da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
da[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (uc & 0x3f));
sp++; // 2 chars
} else {
// 3 bytes, 16 bits
if (dl - dp < 3)
return overflow(src, sp, dst, dp);
da[dp++] = (byte)(0xe0 | ((c >> 12)));
da[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (c & 0x3f));
}
sp++;
}
updatePositions(src, sp, dst, dp);
return CoderResult.UNDERFLOW;
}
private CoderResult encodeBufferLoop(CharBuffer src,
ByteBuffer dst)
{
int mark = src.position();
while (src.hasRemaining()) {
char c = src.get();
if (c < 0x80) {
// Have at most seven bits
if (!dst.hasRemaining())
return overflow(src, mark);
dst.put((byte)c);
} else if (c < 0x800) {
// 2 bytes, 11 bits
if (dst.remaining() < 2)
return overflow(src, mark);
dst.put((byte)(0xc0 | (c >> 6)));
dst.put((byte)(0x80 | (c & 0x3f)));
} else if (Character.isSurrogate(c)) {
// Have a surrogate pair
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, src);
if (uc < 0) {
src.position(mark);
return sgp.error();
}
if (dst.remaining() < 4)
return overflow(src, mark);
dst.put((byte)(0xf0 | ((uc >> 18))));
dst.put((byte)(0x80 | ((uc >> 12) & 0x3f)));
dst.put((byte)(0x80 | ((uc >> 6) & 0x3f)));
dst.put((byte)(0x80 | (uc & 0x3f)));
mark++; // 2 chars
} else {
// 3 bytes, 16 bits
if (dst.remaining() < 3)
return overflow(src, mark);
dst.put((byte)(0xe0 | ((c >> 12))));
dst.put((byte)(0x80 | ((c >> 6) & 0x3f)));
dst.put((byte)(0x80 | (c & 0x3f)));
}
mark++;
}
src.position(mark);
return CoderResult.UNDERFLOW;
}
protected final CoderResult encodeLoop(CharBuffer src,
ByteBuffer dst)
{
if (src.hasArray() && dst.hasArray())
return encodeArrayLoop(src, dst);
else
return encodeBufferLoop(src, dst);
}
private byte repl = (byte)'?';
protected void implReplaceWith(byte[] newReplacement) {
repl = newReplacement[0];
}
// returns -1 if there is malformed char(s) and the
// "action" for malformed input is not REPLACE.
public int encode(char[] sa, int sp, int len, byte[] da) {
int sl = sp + len;
int dp = 0;
int dlASCII = dp + Math.min(len, da.length);
// ASCII only optimized loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
while (sp < sl) {
char c = sa[sp++];
if (c < 0x80) {
// Have at most seven bits
da[dp++] = (byte)c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
da[dp++] = (byte)(0xc0 | (c >> 6));
da[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
if (sgp == null)
sgp = new Surrogate.Parser();
int uc = sgp.parse(c, sa, sp - 1, sl);
if (uc < 0) {
if (malformedInputAction() != CodingErrorAction.REPLACE)
return -1;
da[dp++] = repl;
} else {
da[dp++] = (byte)(0xf0 | ((uc >> 18)));
da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
da[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (uc & 0x3f));
sp++; // 2 chars
}
} else {
// 3 bytes, 16 bits
da[dp++] = (byte)(0xe0 | ((c >> 12)));
da[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
da[dp++] = (byte)(0x80 | (c & 0x3f));
}
}
return dp;
}
public boolean isASCIICompatible() {
return true;
}
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2005, 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.nio.charset.Charset;
abstract class Unicode extends Charset
implements HistoricallyNamedCharset
{
public Unicode(String name, String[] aliases) {
super(name, aliases);
}
public boolean contains(Charset cs) {
return ((cs instanceof US_ASCII)
|| (cs instanceof ISO_8859_1)
|| (cs instanceof ISO_8859_15)
|| (cs instanceof ISO_8859_16)
|| (cs instanceof MS1252)
|| (cs instanceof UTF_8)
|| (cs instanceof UTF_16)
|| (cs instanceof UTF_16BE)
|| (cs instanceof UTF_16LE)
|| (cs instanceof UTF_16LE_BOM)
|| (cs.name().equals("GBK"))
|| (cs.name().equals("GB18030"))
|| (cs.name().equals("ISO-8859-2"))
|| (cs.name().equals("ISO-8859-3"))
|| (cs.name().equals("ISO-8859-4"))
|| (cs.name().equals("ISO-8859-5"))
|| (cs.name().equals("ISO-8859-6"))
|| (cs.name().equals("ISO-8859-7"))
|| (cs.name().equals("ISO-8859-8"))
|| (cs.name().equals("ISO-8859-9"))
|| (cs.name().equals("ISO-8859-13"))
|| (cs.name().equals("JIS_X0201"))
|| (cs.name().equals("x-JIS0208"))
|| (cs.name().equals("JIS_X0212-1990"))
|| (cs.name().equals("GB2312"))
|| (cs.name().equals("EUC-KR"))
|| (cs.name().equals("x-EUC-TW"))
|| (cs.name().equals("EUC-JP"))
|| (cs.name().equals("x-euc-jp-linux"))
|| (cs.name().equals("KOI8-R"))
|| (cs.name().equals("TIS-620"))
|| (cs.name().equals("x-ISCII91"))
|| (cs.name().equals("windows-1251"))
|| (cs.name().equals("windows-1253"))
|| (cs.name().equals("windows-1254"))
|| (cs.name().equals("windows-1255"))
|| (cs.name().equals("windows-1256"))
|| (cs.name().equals("windows-1257"))
|| (cs.name().equals("windows-1258"))
|| (cs.name().equals("windows-932"))
|| (cs.name().equals("x-mswin-936"))
|| (cs.name().equals("x-windows-949"))
|| (cs.name().equals("x-windows-950"))
|| (cs.name().equals("windows-31j"))
|| (cs.name().equals("Big5"))
|| (cs.name().equals("Big5-HKSCS"))
|| (cs.name().equals("x-MS950-HKSCS"))
|| (cs.name().equals("ISO-2022-JP"))
|| (cs.name().equals("ISO-2022-KR"))
|| (cs.name().equals("x-ISO-2022-CN-CNS"))
|| (cs.name().equals("x-ISO-2022-CN-GB"))
|| (cs.name().equals("Big5-HKSCS"))
|| (cs.name().equals("x-Johab"))
|| (cs.name().equals("Shift_JIS")));
}
}

View file

@ -0,0 +1,135 @@
/*
* Copyright (c) 2000, 2006, 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.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.MalformedInputException;
abstract class UnicodeDecoder extends CharsetDecoder {
protected static final char BYTE_ORDER_MARK = (char) 0xfeff;
protected static final char REVERSED_MARK = (char) 0xfffe;
protected static final int NONE = 0;
protected static final int BIG = 1;
protected static final int LITTLE = 2;
private final int expectedByteOrder;
private int currentByteOrder;
private int defaultByteOrder = BIG;
public UnicodeDecoder(Charset cs, int bo) {
super(cs, 0.5f, 1.0f);
expectedByteOrder = currentByteOrder = bo;
}
public UnicodeDecoder(Charset cs, int bo, int defaultBO) {
this(cs, bo);
defaultByteOrder = defaultBO;
}
private char decode(int b1, int b2) {
if (currentByteOrder == BIG)
return (char)((b1 << 8) | b2);
else
return (char)((b2 << 8) | b1);
}
protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
int mark = src.position();
try {
while (src.remaining() > 1) {
int b1 = src.get() & 0xff;
int b2 = src.get() & 0xff;
// Byte Order Mark interpretation
if (currentByteOrder == NONE) {
char c = (char)((b1 << 8) | b2);
if (c == BYTE_ORDER_MARK) {
currentByteOrder = BIG;
mark += 2;
continue;
} else if (c == REVERSED_MARK) {
currentByteOrder = LITTLE;
mark += 2;
continue;
} else {
currentByteOrder = defaultByteOrder;
// FALL THROUGH to process b1, b2 normally
}
}
char c = decode(b1, b2);
if (c == REVERSED_MARK) {
// A reversed BOM cannot occur within middle of stream
return CoderResult.malformedForLength(2);
}
// Surrogates
if (Character.isSurrogate(c)) {
if (Character.isHighSurrogate(c)) {
if (src.remaining() < 2)
return CoderResult.UNDERFLOW;
char c2 = decode(src.get() & 0xff, src.get() & 0xff);
if (!Character.isLowSurrogate(c2))
return CoderResult.malformedForLength(4);
if (dst.remaining() < 2)
return CoderResult.OVERFLOW;
mark += 4;
dst.put(c);
dst.put(c2);
continue;
}
// Unpaired low surrogate
return CoderResult.malformedForLength(2);
}
if (!dst.hasRemaining())
return CoderResult.OVERFLOW;
mark += 2;
dst.put(c);
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected void implReset() {
currentByteOrder = expectedByteOrder;
}
}

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2000, 2010, 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.nio.*;
import java.nio.charset.*;
/**
* Base class for different flavors of UTF-16 encoders
*/
public abstract class UnicodeEncoder extends CharsetEncoder {
protected static final char BYTE_ORDER_MARK = '\uFEFF';
protected static final char REVERSED_MARK = '\uFFFE';
protected static final int BIG = 0;
protected static final int LITTLE = 1;
private int byteOrder; /* Byte order in use */
private boolean usesMark; /* Write an initial BOM */
private boolean needsMark;
protected UnicodeEncoder(Charset cs, int bo, boolean m) {
super(cs, 2.0f,
// Four bytes max if you need a BOM
m ? 4.0f : 2.0f,
// Replacement depends upon byte order
((bo == BIG)
? new byte[] { (byte)0xff, (byte)0xfd }
: new byte[] { (byte)0xfd, (byte)0xff }));
usesMark = needsMark = m;
byteOrder = bo;
}
private void put(char c, ByteBuffer dst) {
if (byteOrder == BIG) {
dst.put((byte)(c >> 8));
dst.put((byte)(c & 0xff));
} else {
dst.put((byte)(c & 0xff));
dst.put((byte)(c >> 8));
}
}
private final Surrogate.Parser sgp = new Surrogate.Parser();
protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
int mark = src.position();
if (needsMark && src.hasRemaining()) {
if (dst.remaining() < 2)
return CoderResult.OVERFLOW;
put(BYTE_ORDER_MARK, dst);
needsMark = false;
}
try {
while (src.hasRemaining()) {
char c = src.get();
if (!Character.isSurrogate(c)) {
if (dst.remaining() < 2)
return CoderResult.OVERFLOW;
mark++;
put(c, dst);
continue;
}
int d = sgp.parse(c, src);
if (d < 0)
return sgp.error();
if (dst.remaining() < 4)
return CoderResult.OVERFLOW;
mark += 2;
put(Character.highSurrogate(d), dst);
put(Character.lowSurrogate(d), dst);
}
return CoderResult.UNDERFLOW;
} finally {
src.position(mark);
}
}
protected void implReset() {
needsMark = usesMark;
}
public boolean canEncode(char c) {
return ! Character.isSurrogate(c);
}
}