Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/cs/ext/DoubleByte.java
38919 views
/*1* Copyright (c) 2009, 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 sun.nio.cs.ArrayDecoder;36import sun.nio.cs.ArrayEncoder;37import static sun.nio.cs.CharsetMapping.*;3839/*40* Four types of "DoubleByte" charsets are implemented in this class41* (1)DoubleByte42* The "mostly widely used" multibyte charset, a combination of43* a singlebyte character set (usually the ASCII charset) and a44* doublebyte character set. The codepoint values of singlebyte45* and doublebyte don't overlap. Microsoft's multibyte charsets46* and IBM's "DBCS_ASCII" charsets, such as IBM1381, 942, 943,47* 948, 949 and 950 are such charsets.48*49* (2)DoubleByte_EBCDIC50* IBM EBCDIC Mix multibyte charset. Use SO and SI to shift (switch)51* in and out between the singlebyte character set and doublebyte52* character set.53*54* (3)DoubleByte_SIMPLE_EUC55* It's a "simple" form of EUC encoding scheme, only have the56* singlebyte character set G0 and one doublebyte character set57* G1 are defined, G2 (with SS2) and G3 (with SS3) are not used.58* So it is actually the same as the "typical" type (1) mentioned59* above, except it return "malformed" for the SS2 and SS3 when60* decoding.61*62* (4)DoubleByte ONLY63* A "pure" doublebyte only character set. From implementation64* point of view, this is the type (1) with "decodeSingle" always65* returns unmappable.66*67* For simplicity, all implementations share the same decoding and68* encoding data structure.69*70* Decoding:71*72* char[][] b2c;73* char[] b2cSB;74* int b2Min, b2Max75*76* public char decodeSingle(int b) {77* return b2cSB.[b];78* }79*80* public char decodeDouble(int b1, int b2) {81* if (b2 < b2Min || b2 > b2Max)82* return UNMAPPABLE_DECODING;83* return b2c[b1][b2 - b2Min];84* }85*86* (1)b2Min, b2Max are the corresponding min and max value of the87* low-half of the double-byte.88* (2)The high 8-bit/b1 of the double-byte are used to indexed into89* b2c array.90*91* Encoding:92*93* char[] c2b;94* char[] c2bIndex;95*96* public int encodeChar(char ch) {97* return c2b[c2bIndex[ch >> 8] + (ch & 0xff)];98* }99*100*/101102public class DoubleByte {103104public final static char[] B2C_UNMAPPABLE;105static {106B2C_UNMAPPABLE = new char[0x100];107Arrays.fill(B2C_UNMAPPABLE, UNMAPPABLE_DECODING);108}109110public static class Decoder extends CharsetDecoder111implements DelegatableDecoder, ArrayDecoder112{113final char[][] b2c;114final char[] b2cSB;115final int b2Min;116final int b2Max;117118// for SimpleEUC override119protected CoderResult crMalformedOrUnderFlow(int b) {120return CoderResult.UNDERFLOW;121}122123protected CoderResult crMalformedOrUnmappable(int b1, int b2) {124if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte(b1)125b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte(b2)126decodeSingle(b2) != UNMAPPABLE_DECODING) { // isSingle(b2)127return CoderResult.malformedForLength(1);128}129return CoderResult.unmappableForLength(2);130}131132Decoder(Charset cs, float avgcpb, float maxcpb,133char[][] b2c, char[] b2cSB,134int b2Min, int b2Max) {135super(cs, avgcpb, maxcpb);136this.b2c = b2c;137this.b2cSB = b2cSB;138this.b2Min = b2Min;139this.b2Max = b2Max;140}141142Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {143this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);144}145146protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {147byte[] sa = src.array();148int sp = src.arrayOffset() + src.position();149int sl = src.arrayOffset() + src.limit();150151char[] da = dst.array();152int dp = dst.arrayOffset() + dst.position();153int dl = dst.arrayOffset() + dst.limit();154155try {156while (sp < sl && dp < dl) {157// inline the decodeSingle/Double() for better performance158int inSize = 1;159int b1 = sa[sp] & 0xff;160char c = b2cSB[b1];161if (c == UNMAPPABLE_DECODING) {162if (sl - sp < 2)163return crMalformedOrUnderFlow(b1);164int b2 = sa[sp + 1] & 0xff;165if (b2 < b2Min || b2 > b2Max ||166(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {167return crMalformedOrUnmappable(b1, b2);168}169inSize++;170}171da[dp++] = c;172sp += inSize;173}174return (sp >= sl) ? CoderResult.UNDERFLOW175: CoderResult.OVERFLOW;176} finally {177src.position(sp - src.arrayOffset());178dst.position(dp - dst.arrayOffset());179}180}181182protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {183int mark = src.position();184try {185186while (src.hasRemaining() && dst.hasRemaining()) {187int b1 = src.get() & 0xff;188char c = b2cSB[b1];189int inSize = 1;190if (c == UNMAPPABLE_DECODING) {191if (src.remaining() < 1)192return crMalformedOrUnderFlow(b1);193int b2 = src.get() & 0xff;194if (b2 < b2Min || b2 > b2Max ||195(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING)196return crMalformedOrUnmappable(b1, b2);197inSize++;198}199dst.put(c);200mark += inSize;201}202return src.hasRemaining()? CoderResult.OVERFLOW203: CoderResult.UNDERFLOW;204} finally {205src.position(mark);206}207}208209// Make some protected methods public for use by JISAutoDetect210public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {211if (src.hasArray() && dst.hasArray())212return decodeArrayLoop(src, dst);213else214return decodeBufferLoop(src, dst);215}216217public int decode(byte[] src, int sp, int len, char[] dst) {218int dp = 0;219int sl = sp + len;220char repl = replacement().charAt(0);221while (sp < sl) {222int b1 = src[sp++] & 0xff;223char c = b2cSB[b1];224if (c == UNMAPPABLE_DECODING) {225if (sp < sl) {226int b2 = src[sp++] & 0xff;227if (b2 < b2Min || b2 > b2Max ||228(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {229if (b2c[b1] == B2C_UNMAPPABLE || // isNotLeadingByte230b2c[b2] != B2C_UNMAPPABLE || // isLeadingByte231decodeSingle(b2) != UNMAPPABLE_DECODING) {232sp--;233}234}235}236if (c == UNMAPPABLE_DECODING) {237c = repl;238}239}240dst[dp++] = c;241}242return dp;243}244245public void implReset() {246super.implReset();247}248249public CoderResult implFlush(CharBuffer out) {250return super.implFlush(out);251}252253// decode loops are not using decodeSingle/Double() for performance254// reason.255public char decodeSingle(int b) {256return b2cSB[b];257}258259public char decodeDouble(int b1, int b2) {260if (b1 < 0 || b1 > b2c.length ||261b2 < b2Min || b2 > b2Max)262return UNMAPPABLE_DECODING;263return b2c[b1][b2 - b2Min];264}265}266267// IBM_EBCDIC_DBCS268public static class Decoder_EBCDIC extends Decoder {269private static final int SBCS = 0;270private static final int DBCS = 1;271private static final int SO = 0x0e;272private static final int SI = 0x0f;273private int currentState;274275Decoder_EBCDIC(Charset cs,276char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {277super(cs, b2c, b2cSB, b2Min, b2Max);278}279280public void implReset() {281currentState = SBCS;282}283284// Check validity of dbcs ebcdic byte pair values285//286// First byte : 0x41 -- 0xFE287// Second byte: 0x41 -- 0xFE288// Doublebyte blank: 0x4040289//290// The validation implementation in "old" DBCS_IBM_EBCDIC and sun.io291// as292// if ((b1 != 0x40 || b2 != 0x40) &&293// (b2 < 0x41 || b2 > 0xfe)) {...}294// is not correct/complete (range check for b1)295//296private static boolean isDoubleByte(int b1, int b2) {297return (0x41 <= b1 && b1 <= 0xfe && 0x41 <= b2 && b2 <= 0xfe)298|| (b1 == 0x40 && b2 == 0x40); // DBCS-HOST SPACE299}300301protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {302byte[] sa = src.array();303int sp = src.arrayOffset() + src.position();304int sl = src.arrayOffset() + src.limit();305char[] da = dst.array();306int dp = dst.arrayOffset() + dst.position();307int dl = dst.arrayOffset() + dst.limit();308309try {310// don't check dp/dl together here, it's possible to311// decdoe a SO/SI without space in output buffer.312while (sp < sl) {313int b1 = sa[sp] & 0xff;314int inSize = 1;315if (b1 == SO) { // Shift out316if (currentState != SBCS)317return CoderResult.malformedForLength(1);318else319currentState = DBCS;320} else if (b1 == SI) {321if (currentState != DBCS)322return CoderResult.malformedForLength(1);323else324currentState = SBCS;325} else {326char c = UNMAPPABLE_DECODING;327if (currentState == SBCS) {328c = b2cSB[b1];329if (c == UNMAPPABLE_DECODING)330return CoderResult.unmappableForLength(1);331} else {332if (sl - sp < 2)333return CoderResult.UNDERFLOW;334int b2 = sa[sp + 1] & 0xff;335if (b2 < b2Min || b2 > b2Max ||336(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {337if (!isDoubleByte(b1, b2))338return CoderResult.malformedForLength(2);339return CoderResult.unmappableForLength(2);340}341inSize++;342}343if (dl - dp < 1)344return CoderResult.OVERFLOW;345346da[dp++] = c;347}348sp += inSize;349}350return CoderResult.UNDERFLOW;351} finally {352src.position(sp - src.arrayOffset());353dst.position(dp - dst.arrayOffset());354}355}356357protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {358int mark = src.position();359try {360while (src.hasRemaining()) {361int b1 = src.get() & 0xff;362int inSize = 1;363if (b1 == SO) { // Shift out364if (currentState != SBCS)365return CoderResult.malformedForLength(1);366else367currentState = DBCS;368} else if (b1 == SI) {369if (currentState != DBCS)370return CoderResult.malformedForLength(1);371else372currentState = SBCS;373} else {374char c = UNMAPPABLE_DECODING;375if (currentState == SBCS) {376c = b2cSB[b1];377if (c == UNMAPPABLE_DECODING)378return CoderResult.unmappableForLength(1);379} else {380if (src.remaining() < 1)381return CoderResult.UNDERFLOW;382int b2 = src.get()&0xff;383if (b2 < b2Min || b2 > b2Max ||384(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {385if (!isDoubleByte(b1, b2))386return CoderResult.malformedForLength(2);387return CoderResult.unmappableForLength(2);388}389inSize++;390}391392if (dst.remaining() < 1)393return CoderResult.OVERFLOW;394395dst.put(c);396}397mark += inSize;398}399return CoderResult.UNDERFLOW;400} finally {401src.position(mark);402}403}404405public int decode(byte[] src, int sp, int len, char[] dst) {406int dp = 0;407int sl = sp + len;408currentState = SBCS;409char repl = replacement().charAt(0);410while (sp < sl) {411int b1 = src[sp++] & 0xff;412if (b1 == SO) { // Shift out413if (currentState != SBCS)414dst[dp++] = repl;415else416currentState = DBCS;417} else if (b1 == SI) {418if (currentState != DBCS)419dst[dp++] = repl;420else421currentState = SBCS;422} else {423char c = UNMAPPABLE_DECODING;424if (currentState == SBCS) {425c = b2cSB[b1];426if (c == UNMAPPABLE_DECODING)427c = repl;428} else {429if (sl == sp) {430c = repl;431} else {432int b2 = src[sp++] & 0xff;433if (b2 < b2Min || b2 > b2Max ||434(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {435c = repl;436}437}438}439dst[dp++] = c;440}441}442return dp;443}444}445446// DBCS_ONLY447public static class Decoder_DBCSONLY extends Decoder {448static final char[] b2cSB_UNMAPPABLE;449static {450b2cSB_UNMAPPABLE = new char[0x100];451Arrays.fill(b2cSB_UNMAPPABLE, UNMAPPABLE_DECODING);452}453Decoder_DBCSONLY(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {454super(cs, 0.5f, 1.0f, b2c, b2cSB_UNMAPPABLE, b2Min, b2Max);455}456}457458// EUC_SIMPLE459// The only thing we need to "override" is to check SS2/SS3 and460// return "malformed" if found461public static class Decoder_EUC_SIM extends Decoder {462private final int SS2 = 0x8E;463private final int SS3 = 0x8F;464465Decoder_EUC_SIM(Charset cs,466char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {467super(cs, b2c, b2cSB, b2Min, b2Max);468}469470// No support provided for G2/G3 for SimpleEUC471protected CoderResult crMalformedOrUnderFlow(int b) {472if (b == SS2 || b == SS3 )473return CoderResult.malformedForLength(1);474return CoderResult.UNDERFLOW;475}476477protected CoderResult crMalformedOrUnmappable(int b1, int b2) {478if (b1 == SS2 || b1 == SS3 )479return CoderResult.malformedForLength(1);480return CoderResult.unmappableForLength(2);481}482483public int decode(byte[] src, int sp, int len, char[] dst) {484int dp = 0;485int sl = sp + len;486char repl = replacement().charAt(0);487while (sp < sl) {488int b1 = src[sp++] & 0xff;489char c = b2cSB[b1];490if (c == UNMAPPABLE_DECODING) {491if (sp < sl) {492int b2 = src[sp++] & 0xff;493if (b2 < b2Min || b2 > b2Max ||494(c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {495if (b1 == SS2 || b1 == SS3) {496sp--;497}498c = repl;499}500} else {501c = repl;502}503}504dst[dp++] = c;505}506return dp;507}508}509510public static class Encoder extends CharsetEncoder511implements ArrayEncoder512{513final int MAX_SINGLEBYTE = 0xff;514private final char[] c2b;515private final char[] c2bIndex;516Surrogate.Parser sgp;517518protected Encoder(Charset cs, char[] c2b, char[] c2bIndex) {519super(cs, 2.0f, 2.0f);520this.c2b = c2b;521this.c2bIndex = c2bIndex;522}523524Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex) {525super(cs, avg, max, repl);526this.c2b = c2b;527this.c2bIndex = c2bIndex;528}529530public boolean canEncode(char c) {531return encodeChar(c) != UNMAPPABLE_ENCODING;532}533534Surrogate.Parser sgp() {535if (sgp == null)536sgp = new Surrogate.Parser();537return sgp;538}539540protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {541char[] sa = src.array();542int sp = src.arrayOffset() + src.position();543int sl = src.arrayOffset() + src.limit();544545byte[] da = dst.array();546int dp = dst.arrayOffset() + dst.position();547int dl = dst.arrayOffset() + dst.limit();548549try {550while (sp < sl) {551char c = sa[sp];552int bb = encodeChar(c);553if (bb == UNMAPPABLE_ENCODING) {554if (Character.isSurrogate(c)) {555if (sgp().parse(c, sa, sp, sl) < 0)556return sgp.error();557return sgp.unmappableResult();558}559return CoderResult.unmappableForLength(1);560}561562if (bb > MAX_SINGLEBYTE) { // DoubleByte563if (dl - dp < 2)564return CoderResult.OVERFLOW;565da[dp++] = (byte)(bb >> 8);566da[dp++] = (byte)bb;567} else { // SingleByte568if (dl - dp < 1)569return CoderResult.OVERFLOW;570da[dp++] = (byte)bb;571}572573sp++;574}575return CoderResult.UNDERFLOW;576} finally {577src.position(sp - src.arrayOffset());578dst.position(dp - dst.arrayOffset());579}580}581582protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {583int mark = src.position();584try {585while (src.hasRemaining()) {586char c = src.get();587int bb = encodeChar(c);588if (bb == UNMAPPABLE_ENCODING) {589if (Character.isSurrogate(c)) {590if (sgp().parse(c, src) < 0)591return sgp.error();592return sgp.unmappableResult();593}594return CoderResult.unmappableForLength(1);595}596if (bb > MAX_SINGLEBYTE) { // DoubleByte597if (dst.remaining() < 2)598return CoderResult.OVERFLOW;599dst.put((byte)(bb >> 8));600dst.put((byte)(bb));601} else {602if (dst.remaining() < 1)603return CoderResult.OVERFLOW;604dst.put((byte)bb);605}606mark++;607}608return CoderResult.UNDERFLOW;609} finally {610src.position(mark);611}612}613614protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {615if (src.hasArray() && dst.hasArray())616return encodeArrayLoop(src, dst);617else618return encodeBufferLoop(src, dst);619}620621protected byte[] repl = replacement();622protected void implReplaceWith(byte[] newReplacement) {623repl = newReplacement;624}625626public int encode(char[] src, int sp, int len, byte[] dst) {627int dp = 0;628int sl = sp + len;629int dl = dst.length;630while (sp < sl) {631char c = src[sp++];632int bb = encodeChar(c);633if (bb == UNMAPPABLE_ENCODING) {634if (Character.isHighSurrogate(c) && sp < sl &&635Character.isLowSurrogate(src[sp])) {636sp++;637}638dst[dp++] = repl[0];639if (repl.length > 1)640dst[dp++] = repl[1];641continue;642} //else643if (bb > MAX_SINGLEBYTE) { // DoubleByte644dst[dp++] = (byte)(bb >> 8);645dst[dp++] = (byte)bb;646} else { // SingleByte647dst[dp++] = (byte)bb;648}649650}651return dp;652}653654public int encodeChar(char ch) {655return c2b[c2bIndex[ch >> 8] + (ch & 0xff)];656}657658// init the c2b and c2bIndex tables from b2c.659static void initC2B(String[] b2c, String b2cSB, String b2cNR, String c2bNR,660int b2Min, int b2Max,661char[] c2b, char[] c2bIndex)662{663Arrays.fill(c2b, (char)UNMAPPABLE_ENCODING);664int off = 0x100;665666char[][] b2c_ca = new char[b2c.length][];667char[] b2cSB_ca = null;668if (b2cSB != null)669b2cSB_ca = b2cSB.toCharArray();670671for (int i = 0; i < b2c.length; i++) {672if (b2c[i] == null)673continue;674b2c_ca[i] = b2c[i].toCharArray();675}676677if (b2cNR != null) {678int j = 0;679while (j < b2cNR.length()) {680char b = b2cNR.charAt(j++);681char c = b2cNR.charAt(j++);682if (b < 0x100 && b2cSB_ca != null) {683if (b2cSB_ca[b] == c)684b2cSB_ca[b] = UNMAPPABLE_DECODING;685} else {686if (b2c_ca[b >> 8][(b & 0xff) - b2Min] == c)687b2c_ca[b >> 8][(b & 0xff) - b2Min] = UNMAPPABLE_DECODING;688}689}690}691692if (b2cSB_ca != null) { // SingleByte693for (int b = 0; b < b2cSB_ca.length; b++) {694char c = b2cSB_ca[b];695if (c == UNMAPPABLE_DECODING)696continue;697int index = c2bIndex[c >> 8];698if (index == 0) {699index = off;700off += 0x100;701c2bIndex[c >> 8] = (char)index;702}703c2b[index + (c & 0xff)] = (char)b;704}705}706707for (int b1 = 0; b1 < b2c.length; b1++) { // DoubleByte708char[] db = b2c_ca[b1];709if (db == null)710continue;711for (int b2 = b2Min; b2 <= b2Max; b2++) {712char c = db[b2 - b2Min];713if (c == UNMAPPABLE_DECODING)714continue;715int index = c2bIndex[c >> 8];716if (index == 0) {717index = off;718off += 0x100;719c2bIndex[c >> 8] = (char)index;720}721c2b[index + (c & 0xff)] = (char)((b1 << 8) | b2);722}723}724725if (c2bNR != null) {726// add c->b only nr entries727for (int i = 0; i < c2bNR.length(); i += 2) {728char b = c2bNR.charAt(i);729char c = c2bNR.charAt(i + 1);730int index = (c >> 8);731if (c2bIndex[index] == 0) {732c2bIndex[index] = (char)off;733off += 0x100;734}735index = c2bIndex[index] + (c & 0xff);736c2b[index] = b;737}738}739}740}741742public static class Encoder_DBCSONLY extends Encoder {743Encoder_DBCSONLY(Charset cs, byte[] repl,744char[] c2b, char[] c2bIndex) {745super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex);746}747748public int encodeChar(char ch) {749int bb = super.encodeChar(ch);750if (bb <= MAX_SINGLEBYTE)751return UNMAPPABLE_ENCODING;752return bb;753}754}755756757758public static class Encoder_EBCDIC extends Encoder {759static final int SBCS = 0;760static final int DBCS = 1;761static final byte SO = 0x0e;762static final byte SI = 0x0f;763764protected int currentState = SBCS;765766Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex) {767super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex);768}769770protected void implReset() {771currentState = SBCS;772}773774protected CoderResult implFlush(ByteBuffer out) {775if (currentState == DBCS) {776if (out.remaining() < 1)777return CoderResult.OVERFLOW;778out.put(SI);779}780implReset();781return CoderResult.UNDERFLOW;782}783784protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {785char[] sa = src.array();786int sp = src.arrayOffset() + src.position();787int sl = src.arrayOffset() + src.limit();788byte[] da = dst.array();789int dp = dst.arrayOffset() + dst.position();790int dl = dst.arrayOffset() + dst.limit();791792try {793while (sp < sl) {794char c = sa[sp];795int bb = encodeChar(c);796if (bb == UNMAPPABLE_ENCODING) {797if (Character.isSurrogate(c)) {798if (sgp().parse(c, sa, sp, sl) < 0)799return sgp.error();800return sgp.unmappableResult();801}802return CoderResult.unmappableForLength(1);803}804if (bb > MAX_SINGLEBYTE) { // DoubleByte805if (currentState == SBCS) {806if (dl - dp < 1)807return CoderResult.OVERFLOW;808currentState = DBCS;809da[dp++] = SO;810}811if (dl - dp < 2)812return CoderResult.OVERFLOW;813da[dp++] = (byte)(bb >> 8);814da[dp++] = (byte)bb;815} else { // SingleByte816if (currentState == DBCS) {817if (dl - dp < 1)818return CoderResult.OVERFLOW;819currentState = SBCS;820da[dp++] = SI;821}822if (dl - dp < 1)823return CoderResult.OVERFLOW;824da[dp++] = (byte)bb;825826}827sp++;828}829return CoderResult.UNDERFLOW;830} finally {831src.position(sp - src.arrayOffset());832dst.position(dp - dst.arrayOffset());833}834}835836protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {837int mark = src.position();838try {839while (src.hasRemaining()) {840char c = src.get();841int bb = encodeChar(c);842if (bb == UNMAPPABLE_ENCODING) {843if (Character.isSurrogate(c)) {844if (sgp().parse(c, src) < 0)845return sgp.error();846return sgp.unmappableResult();847}848return CoderResult.unmappableForLength(1);849}850if (bb > MAX_SINGLEBYTE) { // DoubleByte851if (currentState == SBCS) {852if (dst.remaining() < 1)853return CoderResult.OVERFLOW;854currentState = DBCS;855dst.put(SO);856}857if (dst.remaining() < 2)858return CoderResult.OVERFLOW;859dst.put((byte)(bb >> 8));860dst.put((byte)(bb));861} else { // Single-byte862if (currentState == DBCS) {863if (dst.remaining() < 1)864return CoderResult.OVERFLOW;865currentState = SBCS;866dst.put(SI);867}868if (dst.remaining() < 1)869return CoderResult.OVERFLOW;870dst.put((byte)bb);871}872mark++;873}874return CoderResult.UNDERFLOW;875} finally {876src.position(mark);877}878}879880public int encode(char[] src, int sp, int len, byte[] dst) {881int dp = 0;882int sl = sp + len;883while (sp < sl) {884char c = src[sp++];885int bb = encodeChar(c);886887if (bb == UNMAPPABLE_ENCODING) {888if (Character.isHighSurrogate(c) && sp < sl &&889Character.isLowSurrogate(src[sp])) {890sp++;891}892dst[dp++] = repl[0];893if (repl.length > 1)894dst[dp++] = repl[1];895continue;896} //else897if (bb > MAX_SINGLEBYTE) { // DoubleByte898if (currentState == SBCS) {899currentState = DBCS;900dst[dp++] = SO;901}902dst[dp++] = (byte)(bb >> 8);903dst[dp++] = (byte)bb;904} else { // SingleByte905if (currentState == DBCS) {906currentState = SBCS;907dst[dp++] = SI;908}909dst[dp++] = (byte)bb;910}911}912913if (currentState == DBCS) {914currentState = SBCS;915dst[dp++] = SI;916}917return dp;918}919}920921// EUC_SIMPLE922public static class Encoder_EUC_SIM extends Encoder {923Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex) {924super(cs, c2b, c2bIndex);925}926}927928}929930931