Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/cs/ext/HKSCS.java
38919 views
/*1* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.cs.ext;2627import java.nio.ByteBuffer;28import java.nio.CharBuffer;29import java.nio.charset.Charset;30import java.nio.charset.CharsetDecoder;31import java.nio.charset.CharsetEncoder;32import java.nio.charset.CoderResult;33import java.util.Arrays;34import sun.nio.cs.Surrogate;35import static sun.nio.cs.CharsetMapping.*;3637public class HKSCS {3839public static class Decoder extends DoubleByte.Decoder {40static int b2Min = 0x40;41static int b2Max = 0xfe;4243private char[][] b2cBmp;44private char[][] b2cSupp;45private DoubleByte.Decoder big5Dec;4647protected Decoder(Charset cs,48DoubleByte.Decoder big5Dec,49char[][] b2cBmp, char[][] b2cSupp)50{51// super(cs, 0.5f, 1.0f);52// need to extends DoubleByte.Decoder so the53// sun.io can use it. this implementation54super(cs, 0.5f, 1.0f, null, null, 0, 0);55this.big5Dec = big5Dec;56this.b2cBmp = b2cBmp;57this.b2cSupp = b2cSupp;58}5960public char decodeSingle(int b) {61return big5Dec.decodeSingle(b);62}6364public char decodeBig5(int b1, int b2) {65return big5Dec.decodeDouble(b1, b2);66}6768public char decodeDouble(int b1, int b2) {69return b2cBmp[b1][b2 - b2Min];70}7172public char decodeDoubleEx(int b1, int b2) {73/* if the b2cSupp is null, the subclass need74to override the methold75if (b2cSupp == null)76return UNMAPPABLE_DECODING;77*/78return b2cSupp[b1][b2 - b2Min];79}8081protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {82byte[] sa = src.array();83int sp = src.arrayOffset() + src.position();84int sl = src.arrayOffset() + src.limit();8586char[] da = dst.array();87int dp = dst.arrayOffset() + dst.position();88int dl = dst.arrayOffset() + dst.limit();8990try {91while (sp < sl) {92int b1 = sa[sp] & 0xff;93char c = decodeSingle(b1);94int inSize = 1, outSize = 1;95char[] cc = null;96if (c == UNMAPPABLE_DECODING) {97if (sl - sp < 2)98return CoderResult.UNDERFLOW;99int b2 = sa[sp + 1] & 0xff;100inSize++;101if (b2 < b2Min || b2 > b2Max)102return CoderResult.unmappableForLength(2);103c = decodeDouble(b1, b2); //bmp104if (c == UNMAPPABLE_DECODING) {105c = decodeDoubleEx(b1, b2); //supp106if (c == UNMAPPABLE_DECODING) {107c = decodeBig5(b1, b2); //big5108if (c == UNMAPPABLE_DECODING)109return CoderResult.unmappableForLength(2);110} else {111// supplementary character in u+2xxxx area112outSize = 2;113}114}115}116if (dl - dp < outSize)117return CoderResult.OVERFLOW;118if (outSize == 2) {119// supplementary characters120da[dp++] = Surrogate.high(0x20000 + c);121da[dp++] = Surrogate.low(0x20000 + c);122} else {123da[dp++] = c;124}125sp += inSize;126}127return CoderResult.UNDERFLOW;128} finally {129src.position(sp - src.arrayOffset());130dst.position(dp - dst.arrayOffset());131}132}133134protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {135int mark = src.position();136try {137while (src.hasRemaining()) {138char[] cc = null;139int b1 = src.get() & 0xff;140int inSize = 1, outSize = 1;141char c = decodeSingle(b1);142if (c == UNMAPPABLE_DECODING) {143if (src.remaining() < 1)144return CoderResult.UNDERFLOW;145int b2 = src.get() & 0xff;146inSize++;147if (b2 < b2Min || b2 > b2Max)148return CoderResult.unmappableForLength(2);149c = decodeDouble(b1, b2); //bmp150if (c == UNMAPPABLE_DECODING) {151c = decodeDoubleEx(b1, b2); //supp152if (c == UNMAPPABLE_DECODING) {153c = decodeBig5(b1, b2); //big5154if (c == UNMAPPABLE_DECODING)155return CoderResult.unmappableForLength(2);156} else {157outSize = 2;158}159}160}161if (dst.remaining() < outSize)162return CoderResult.OVERFLOW;163if (outSize == 2) {164dst.put(Surrogate.high(0x20000 + c));165dst.put(Surrogate.low(0x20000 + c));166} else {167dst.put(c);168}169mark += inSize;170}171return CoderResult.UNDERFLOW;172} finally {173src.position(mark);174}175}176177public int decode(byte[] src, int sp, int len, char[] dst) {178int dp = 0;179int sl = sp + len;180char repl = replacement().charAt(0);181while (sp < sl) {182int b1 = src[sp++] & 0xff;183char c = decodeSingle(b1);184if (c == UNMAPPABLE_DECODING) {185if (sl == sp) {186c = repl;187} else {188int b2 = src[sp++] & 0xff;189if (b2 < b2Min || b2 > b2Max) {190c = repl;191} else if ((c = decodeDouble(b1, b2)) == UNMAPPABLE_DECODING) {192c = decodeDoubleEx(b1, b2); //supp193if (c == UNMAPPABLE_DECODING) {194c = decodeBig5(b1, b2); //big5195if (c == UNMAPPABLE_DECODING)196c = repl;197} else {198// supplementary character in u+2xxxx area199dst[dp++] = Surrogate.high(0x20000 + c);200dst[dp++] = Surrogate.low(0x20000 + c);201continue;202}203}204}205}206dst[dp++] = c;207}208return dp;209}210211public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {212if (src.hasArray() && dst.hasArray())213return decodeArrayLoop(src, dst);214else215return decodeBufferLoop(src, dst);216}217218static void initb2c(char[][]b2c, String[] b2cStr)219{220for (int i = 0; i < b2cStr.length; i++) {221if (b2cStr[i] == null)222b2c[i] = DoubleByte.B2C_UNMAPPABLE;223else224b2c[i] = b2cStr[i].toCharArray();225}226}227228}229230public static class Encoder extends DoubleByte.Encoder {231private DoubleByte.Encoder big5Enc;232private char[][] c2bBmp;233private char[][] c2bSupp;234235protected Encoder(Charset cs,236DoubleByte.Encoder big5Enc,237char[][] c2bBmp,238char[][] c2bSupp)239{240super(cs, null, null);241this.big5Enc = big5Enc;242this.c2bBmp = c2bBmp;243this.c2bSupp = c2bSupp;244}245246public int encodeBig5(char ch) {247return big5Enc.encodeChar(ch);248}249250public int encodeChar(char ch) {251int bb = c2bBmp[ch >> 8][ch & 0xff];252if (bb == UNMAPPABLE_ENCODING)253return encodeBig5(ch);254return bb;255}256257public int encodeSupp(int cp) {258if ((cp & 0xf0000) != 0x20000)259return UNMAPPABLE_ENCODING;260return c2bSupp[(cp >> 8) & 0xff][cp & 0xff];261}262263public boolean canEncode(char c) {264return encodeChar(c) != UNMAPPABLE_ENCODING;265}266267protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {268char[] sa = src.array();269int sp = src.arrayOffset() + src.position();270int sl = src.arrayOffset() + src.limit();271272byte[] da = dst.array();273int dp = dst.arrayOffset() + dst.position();274int dl = dst.arrayOffset() + dst.limit();275276try {277while (sp < sl) {278char c = sa[sp];279int inSize = 1;280int bb = encodeChar(c);281if (bb == UNMAPPABLE_ENCODING) {282if (Character.isSurrogate(c)) {283int cp;284if ((cp = sgp().parse(c, sa, sp, sl)) < 0)285return sgp.error();286bb = encodeSupp(cp);287if (bb == UNMAPPABLE_ENCODING)288return CoderResult.unmappableForLength(2);289inSize = 2;290} else {291return CoderResult.unmappableForLength(1);292}293}294if (bb > MAX_SINGLEBYTE) { // DoubleByte295if (dl - dp < 2)296return CoderResult.OVERFLOW;297da[dp++] = (byte)(bb >> 8);298da[dp++] = (byte)bb;299} else { // SingleByte300if (dl - dp < 1)301return CoderResult.OVERFLOW;302da[dp++] = (byte)bb;303}304sp += inSize;305}306return CoderResult.UNDERFLOW;307} finally {308src.position(sp - src.arrayOffset());309dst.position(dp - dst.arrayOffset());310}311}312313protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {314int mark = src.position();315try {316while (src.hasRemaining()) {317int inSize = 1;318char c = src.get();319int bb = encodeChar(c);320if (bb == UNMAPPABLE_ENCODING) {321if (Character.isSurrogate(c)) {322int cp;323if ((cp = sgp().parse(c, src)) < 0)324return sgp.error();325bb = encodeSupp(cp);326if (bb == UNMAPPABLE_ENCODING)327return CoderResult.unmappableForLength(2);328inSize = 2;329} else {330return CoderResult.unmappableForLength(1);331}332}333if (bb > MAX_SINGLEBYTE) { // DoubleByte334if (dst.remaining() < 2)335return CoderResult.OVERFLOW;336dst.put((byte)(bb >> 8));337dst.put((byte)(bb));338} else {339if (dst.remaining() < 1)340return CoderResult.OVERFLOW;341dst.put((byte)bb);342}343mark += inSize;344}345return CoderResult.UNDERFLOW;346} finally {347src.position(mark);348}349}350351protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {352if (src.hasArray() && dst.hasArray())353return encodeArrayLoop(src, dst);354else355return encodeBufferLoop(src, dst);356}357358private byte[] repl = replacement();359protected void implReplaceWith(byte[] newReplacement) {360repl = newReplacement;361}362363public int encode(char[] src, int sp, int len, byte[] dst) {364int dp = 0;365int sl = sp + len;366while (sp < sl) {367char c = src[sp++];368int bb = encodeChar(c);369if (bb == UNMAPPABLE_ENCODING) {370if (!Character.isHighSurrogate(c) || sp == sl ||371!Character.isLowSurrogate(src[sp]) ||372(bb = encodeSupp(Character.toCodePoint(c, src[sp++])))373== UNMAPPABLE_ENCODING) {374dst[dp++] = repl[0];375if (repl.length > 1)376dst[dp++] = repl[1];377continue;378}379}380if (bb > MAX_SINGLEBYTE) { // DoubleByte381dst[dp++] = (byte)(bb >> 8);382dst[dp++] = (byte)bb;383} else { // SingleByte384dst[dp++] = (byte)bb;385}386}387return dp;388}389390391static char[] C2B_UNMAPPABLE = new char[0x100];392static {393Arrays.fill(C2B_UNMAPPABLE, (char)UNMAPPABLE_ENCODING);394}395396static void initc2b(char[][] c2b, String[] b2cStr, String pua) {397// init c2b/c2bSupp from b2cStr and supp398int b2Min = 0x40;399Arrays.fill(c2b, C2B_UNMAPPABLE);400for (int b1 = 0; b1 < 0x100; b1++) {401String s = b2cStr[b1];402if (s == null)403continue;404for (int i = 0; i < s.length(); i++) {405char c = s.charAt(i);406int hi = c >> 8;407if (c2b[hi] == C2B_UNMAPPABLE) {408c2b[hi] = new char[0x100];409Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);410}411c2b[hi][c & 0xff] = (char)((b1 << 8) | (i + b2Min));412}413}414if (pua != null) { // add the compatibility pua entries415char c = '\ue000'; //first pua character416for (int i = 0; i < pua.length(); i++) {417char bb = pua.charAt(i);418if (bb != UNMAPPABLE_DECODING) {419int hi = c >> 8;420if (c2b[hi] == C2B_UNMAPPABLE) {421c2b[hi] = new char[0x100];422Arrays.fill(c2b[hi], (char)UNMAPPABLE_ENCODING);423}424c2b[hi][c & 0xff] = bb;425}426c++;427}428}429}430}431}432433434