| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.nio.cs.ext;  | 
 | 
 | 
 | 
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;  | 
 | 
import sun.nio.cs.HistoricallyNamedCharset;  | 
 | 
import sun.nio.cs.Surrogate;  | 
 | 
import sun.nio.cs.US_ASCII;  | 
 | 
import static sun.nio.cs.CharsetMapping.*;  | 
 | 
 | 
 | 
/*  | 
 | 
 * Implementation notes:  | 
 | 
 *  | 
 | 
 * (1)"Standard based" (ASCII, JIS_X_0201 and JIS_X_0208) ISO2022-JP charset  | 
 | 
 * is provided by the base implementation of this class.  | 
 | 
 *  | 
 | 
 * Three Microsoft ISO2022-JP variants, MS50220, MS50221 and MSISO2022JP  | 
 | 
 * are provided via subclasses.  | 
 | 
 *  | 
 | 
 * (2)MS50220 and MS50221 are assumed to work the same way as Microsoft  | 
 | 
 * CP50220 and CP50221's 7-bit implementation works by using CP5022X  | 
 | 
 * specific JIS0208 and JIS0212 mapping tables (generated via Microsoft's  | 
 | 
 * MultiByteToWideChar/WideCharToMultiByte APIs). The only difference  | 
 | 
 * between these 2 classes is that MS50220 does not support singlebyte  | 
 | 
 * halfwidth kana (Uff61-Uff9f) shiftin mechanism when "encoding", instead  | 
 | 
 * these halfwidth kana characters are converted to their fullwidth JIS0208  | 
 | 
 * counterparts.  | 
 | 
 *  | 
 | 
 * The difference between the standard JIS_X_0208 and JIS_X_0212 mappings  | 
 | 
 * and the CP50220/50221 specific are  | 
 | 
 *  | 
 | 
 * 0208 mapping:  | 
 | 
 *              1)0x213d <-> U2015 (compared to U2014)  | 
 | 
 *              2)One way mappings for 5 characters below  | 
 | 
 *                u2225 (ms) -> 0x2142 <-> u2016 (jis)  | 
 | 
 *                uff0d (ms) -> 0x215d <-> u2212 (jis)  | 
 | 
 *                uffe0 (ms) -> 0x2171 <-> u00a2 (jis)  | 
 | 
 *                uffe1 (ms) -> 0x2172 <-> u00a3 (jis)  | 
 | 
 *                uffe2 (ms) -> 0x224c <-> u00ac (jis)  | 
 | 
 *                //should consider 0xff5e -> 0x2141 <-> U301c?  | 
 | 
 *              3)NEC Row13 0x2d21-0x2d79  | 
 | 
 *              4)85-94 ku <-> UE000,UE3AB (includes NEC selected  | 
 | 
 *                IBM kanji in 89-92ku)  | 
 | 
 *              5)UFF61-UFF9f -> Fullwidth 0208 KANA  | 
 | 
 *  | 
 | 
 * 0212 mapping:  | 
 | 
 *              1)0x2237 <-> UFF5E (Fullwidth Tilde)  | 
 | 
 *              2)0x2271 <-> U2116 (Numero Sign)  | 
 | 
 *              3)85-94 ku <-> UE3AC - UE757  | 
 | 
 *  | 
 | 
 * (3)MSISO2022JP uses a JIS0208 mapping generated from MS932DB.b2c  | 
 | 
 * and MS932DB.c2b by converting the SJIS codepoints back to their  | 
 | 
 * JIS0208 counterparts. With the exception of  | 
 | 
 *  | 
 | 
 * (a)Codepoints with a resulting JIS0208 codepoints beyond 0x7e00 are  | 
 | 
 *    dropped (this includs the IBM Extended Kanji/Non-kanji from 0x9321  | 
 | 
 *    to 0x972c)  | 
 | 
 * (b)The Unicode codepoints that the IBM Extended Kanji/Non-kanji are  | 
 | 
 *    mapped to (in MS932) are mapped back to NEC selected IBM Kanji/  | 
 | 
 *    Non-kanji area at 0x7921-0x7c7e.  | 
 | 
 *  | 
 | 
 * Compared to JIS_X_0208 mapping, this MS932 based mapping has  | 
 | 
 | 
 | 
 * (a)different mappings for 7 JIS codepoints  | 
 | 
 *        0x213d <-> U2015  | 
 | 
 *        0x2141 <-> UFF5E  | 
 | 
 *        0x2142 <-> U2225  | 
 | 
 *        0x215d <-> Uff0d  | 
 | 
 *        0x2171 <-> Uffe0  | 
 | 
 *        0x2172 <-> Uffe1  | 
 | 
 *        0x224c <-> Uffe2  | 
 | 
 * (b)added one-way c2b mappings for  | 
 | 
 *        U00b8 -> 0x2124  | 
 | 
 *        U00b7 -> 0x2126  | 
 | 
 *        U00af -> 0x2131  | 
 | 
 *        U00ab -> 0x2263  | 
 | 
 *        U00bb -> 0x2264  | 
 | 
 *        U3094 -> 0x2574  | 
 | 
 *        U00b5 -> 0x264c  | 
 | 
 * (c)NEC Row 13  | 
 | 
 * (d)NEC selected IBM extended Kanji/Non-kanji  | 
 | 
 *    These codepoints are mapped to the same Unicode codepoints as  | 
 | 
 *    the MS932 does, while MS50220/50221 maps them to the Unicode  | 
 | 
 *    private area.  | 
 | 
 *  | 
 | 
 * # There is also an interesting difference when compared to MS5022X  | 
 | 
 *   0208 mapping for JIS codepoint "0x2D60", MS932 maps it to U301d  | 
 | 
 *   but MS5022X maps it to U301e, obvious MS5022X is wrong, but...  | 
 | 
 */  | 
 | 
 | 
 | 
public class ISO2022_JP  | 
 | 
    extends Charset  | 
 | 
    implements HistoricallyNamedCharset  | 
 | 
{ | 
 | 
    private static final int ASCII = 0;                   | 
 | 
    private static final int JISX0201_1976 = 1;           | 
 | 
    private static final int JISX0208_1978 = 2;           | 
 | 
    private static final int JISX0208_1983 = 3;           | 
 | 
    private static final int JISX0212_1990 = 4;           | 
 | 
    private static final int JISX0201_1976_KANA = 5;      | 
 | 
    private static final int SHIFTOUT = 6;  | 
 | 
 | 
 | 
    private static final int ESC = 0x1b;  | 
 | 
    private static final int SO = 0x0e;  | 
 | 
    private static final int SI = 0x0f;  | 
 | 
 | 
 | 
    public ISO2022_JP() { | 
 | 
        super("ISO-2022-JP", | 
 | 
              ExtendedCharsets.aliasesFor("ISO-2022-JP")); | 
 | 
    }  | 
 | 
 | 
 | 
    protected ISO2022_JP(String canonicalName,  | 
 | 
                         String[] aliases) { | 
 | 
        super(canonicalName, aliases);  | 
 | 
    }  | 
 | 
 | 
 | 
    public String historicalName() { | 
 | 
        return "ISO2022JP";  | 
 | 
    }  | 
 | 
 | 
 | 
    public boolean contains(Charset cs) { | 
 | 
        return ((cs instanceof JIS_X_0201)  | 
 | 
                || (cs instanceof US_ASCII)  | 
 | 
                || (cs instanceof JIS_X_0208)  | 
 | 
                || (cs instanceof ISO2022_JP));  | 
 | 
    }  | 
 | 
 | 
 | 
    public CharsetDecoder newDecoder() { | 
 | 
        return new Decoder(this);  | 
 | 
    }  | 
 | 
 | 
 | 
    public CharsetEncoder newEncoder() { | 
 | 
        return new Encoder(this);  | 
 | 
    }  | 
 | 
 | 
 | 
    protected boolean doSBKANA() { | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
    static class Decoder extends CharsetDecoder  | 
 | 
        implements DelegatableDecoder { | 
 | 
 | 
 | 
        final static DoubleByte.Decoder DEC0208 =  | 
 | 
            (DoubleByte.Decoder)new JIS_X_0208().newDecoder();  | 
 | 
 | 
 | 
        private int currentState;  | 
 | 
        private int previousState;  | 
 | 
 | 
 | 
        private DoubleByte.Decoder dec0208;  | 
 | 
        private DoubleByte.Decoder dec0212;  | 
 | 
 | 
 | 
        private Decoder(Charset cs) { | 
 | 
            this(cs, DEC0208, null);  | 
 | 
        }  | 
 | 
 | 
 | 
        protected Decoder(Charset cs,  | 
 | 
                          DoubleByte.Decoder dec0208,  | 
 | 
                          DoubleByte.Decoder dec0212) { | 
 | 
            super(cs, 0.5f, 1.0f);  | 
 | 
            this.dec0208 = dec0208;  | 
 | 
            this.dec0212 = dec0212;  | 
 | 
            currentState = ASCII;  | 
 | 
            previousState = ASCII;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void implReset() { | 
 | 
            currentState = ASCII;  | 
 | 
            previousState = ASCII;  | 
 | 
        }  | 
 | 
 | 
 | 
        private CoderResult decodeArrayLoop(ByteBuffer src,  | 
 | 
                                            CharBuffer dst)  | 
 | 
        { | 
 | 
            int inputSize = 0;  | 
 | 
            int b1 = 0, b2 = 0, b3 = 0, b4 = 0;  | 
 | 
            char c = UNMAPPABLE_DECODING;  | 
 | 
            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) { | 
 | 
                    b1 = sa[sp] & 0xff;  | 
 | 
                    inputSize = 1;  | 
 | 
                    if ((b1 & 0x80) != 0) { | 
 | 
                        return CoderResult.malformedForLength(inputSize);  | 
 | 
                    }  | 
 | 
                    if (b1 == ESC || b1 == SO || b1 == SI) { | 
 | 
                        if (b1 == ESC) { | 
 | 
                            if (sp + inputSize + 2 > sl)  | 
 | 
                                return CoderResult.UNDERFLOW;  | 
 | 
                            b2 = sa[sp + inputSize++] & 0xff;  | 
 | 
                            if (b2 == '(') { | 
 | 
                                b3 = sa[sp + inputSize++] & 0xff;  | 
 | 
                                if (b3 == 'B'){ | 
 | 
                                    currentState = ASCII;  | 
 | 
                                } else if (b3 == 'J'){ | 
 | 
                                    currentState = JISX0201_1976;  | 
 | 
                                } else if (b3 == 'I'){ | 
 | 
                                    currentState = JISX0201_1976_KANA;  | 
 | 
                                } else { | 
 | 
                                    return CoderResult.malformedForLength(inputSize);  | 
 | 
                                }  | 
 | 
                            } else if (b2 == '$'){ | 
 | 
                                b3 = sa[sp + inputSize++] & 0xff;  | 
 | 
                                if (b3 == '@'){ | 
 | 
                                    currentState = JISX0208_1978;  | 
 | 
                                } else if (b3 == 'B'){ | 
 | 
                                    currentState = JISX0208_1983;  | 
 | 
                                } else if (b3 == '(' && dec0212 != null) { | 
 | 
                                    if (sp + inputSize + 1 > sl)  | 
 | 
                                        return CoderResult.UNDERFLOW;  | 
 | 
                                    b4 = sa[sp + inputSize++] & 0xff;  | 
 | 
                                    if (b4 == 'D') { | 
 | 
                                        currentState = JISX0212_1990;  | 
 | 
                                    } else { | 
 | 
                                        return CoderResult.malformedForLength(inputSize);  | 
 | 
                                    }  | 
 | 
                                } else { | 
 | 
                                    return CoderResult.malformedForLength(inputSize);  | 
 | 
                                }  | 
 | 
                            } else { | 
 | 
                                return CoderResult.malformedForLength(inputSize);  | 
 | 
                            }  | 
 | 
                        } else if (b1 == SO) { | 
 | 
                            previousState = currentState;  | 
 | 
                            currentState = SHIFTOUT;  | 
 | 
                        } else if (b1 == SI) { | 
 | 
                            currentState = previousState;  | 
 | 
                        }  | 
 | 
                        sp += inputSize;  | 
 | 
                        continue;  | 
 | 
                    }  | 
 | 
                    if (dp + 1 > dl)  | 
 | 
                        return CoderResult.OVERFLOW;  | 
 | 
 | 
 | 
                    switch (currentState){ | 
 | 
                        case ASCII:  | 
 | 
                            da[dp++] = (char)(b1 & 0xff);  | 
 | 
                            break;  | 
 | 
                        case JISX0201_1976:  | 
 | 
                          switch (b1) { | 
 | 
                              case 0x5c:    | 
 | 
                                da[dp++] = '\u00a5';  | 
 | 
                                break;  | 
 | 
                              case 0x7e:  | 
 | 
                                da[dp++] = '\u203e';  | 
 | 
                                break;  | 
 | 
                              default:  | 
 | 
                                da[dp++] = (char)b1;  | 
 | 
                                break;  | 
 | 
                            }  | 
 | 
                            break;  | 
 | 
                        case JISX0208_1978:  | 
 | 
                        case JISX0208_1983:  | 
 | 
                            if (sp + inputSize + 1 > sl)  | 
 | 
                                return CoderResult.UNDERFLOW;  | 
 | 
                            b2 = sa[sp + inputSize++] & 0xff;  | 
 | 
                            c = dec0208.decodeDouble(b1,b2);  | 
 | 
                            if (c == UNMAPPABLE_DECODING)  | 
 | 
                                return CoderResult.unmappableForLength(inputSize);  | 
 | 
                            da[dp++] = c;  | 
 | 
                            break;  | 
 | 
                        case JISX0212_1990:  | 
 | 
                            if (sp + inputSize + 1 > sl)  | 
 | 
                                return CoderResult.UNDERFLOW;  | 
 | 
                            b2 = sa[sp + inputSize++] & 0xff;  | 
 | 
                            c = dec0212.decodeDouble(b1,b2);  | 
 | 
                            if (c == UNMAPPABLE_DECODING)  | 
 | 
                                return CoderResult.unmappableForLength(inputSize);  | 
 | 
                            da[dp++] = c;  | 
 | 
                            break;  | 
 | 
                        case JISX0201_1976_KANA:  | 
 | 
                        case SHIFTOUT:  | 
 | 
                            if (b1 > 0x5f) { | 
 | 
                                return CoderResult.malformedForLength(inputSize);  | 
 | 
                            }  | 
 | 
                            da[dp++] = (char)(b1 + 0xff40);  | 
 | 
                            break;  | 
 | 
                    }  | 
 | 
                    sp += inputSize;  | 
 | 
                }  | 
 | 
                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();  | 
 | 
            int b1 = 0, b2 = 0, b3 = 0, b4=0;  | 
 | 
            char c = UNMAPPABLE_DECODING;  | 
 | 
            int inputSize = 0;  | 
 | 
            try { | 
 | 
                while (src.hasRemaining()) { | 
 | 
                    b1 = src.get() & 0xff;  | 
 | 
                    inputSize = 1;  | 
 | 
                    if ((b1 & 0x80) != 0)  | 
 | 
                        return CoderResult.malformedForLength(inputSize);  | 
 | 
                    if (b1 == ESC || b1 == SO || b1 == SI) { | 
 | 
                        if (b1 == ESC) {   | 
 | 
                            if (src.remaining() < 2)  | 
 | 
                                return CoderResult.UNDERFLOW;  | 
 | 
                            b2 = src.get() & 0xff;  | 
 | 
                            inputSize++;  | 
 | 
                            if (b2 == '(') { | 
 | 
                                b3 = src.get() & 0xff;  | 
 | 
                                inputSize++;  | 
 | 
                                if (b3 == 'B'){ | 
 | 
                                    currentState = ASCII;  | 
 | 
                                } else if (b3 == 'J'){ | 
 | 
                                    currentState = JISX0201_1976;  | 
 | 
                                } else if (b3 == 'I'){ | 
 | 
                                    currentState = JISX0201_1976_KANA;  | 
 | 
                                } else { | 
 | 
                                   return CoderResult.malformedForLength(inputSize);  | 
 | 
                                }  | 
 | 
                            } else if (b2 == '$'){ | 
 | 
                                b3 = src.get() & 0xff;  | 
 | 
                                inputSize++;  | 
 | 
                                if (b3 == '@'){ | 
 | 
                                    currentState = JISX0208_1978;  | 
 | 
                                } else if (b3 == 'B'){ | 
 | 
                                    currentState = JISX0208_1983;  | 
 | 
                                } else if (b3 == '(' && dec0212 != null) { | 
 | 
                                    if (!src.hasRemaining())  | 
 | 
                                        return CoderResult.UNDERFLOW;  | 
 | 
                                    b4 = src.get() & 0xff;  | 
 | 
                                    inputSize++;  | 
 | 
                                    if (b4 == 'D') { | 
 | 
                                        currentState = JISX0212_1990;  | 
 | 
                                    } else { | 
 | 
                                        return CoderResult.malformedForLength(inputSize);  | 
 | 
                                    }  | 
 | 
                                } else { | 
 | 
                                    return CoderResult.malformedForLength(inputSize);  | 
 | 
                                }  | 
 | 
                            } else { | 
 | 
                                return CoderResult.malformedForLength(inputSize);  | 
 | 
                            }  | 
 | 
                        } else if (b1 == SO) { | 
 | 
                            previousState = currentState;  | 
 | 
                            currentState = SHIFTOUT;  | 
 | 
                        } else if (b1 == SI) {  | 
 | 
                            currentState = previousState;  | 
 | 
                        }  | 
 | 
                        mark += inputSize;  | 
 | 
                        continue;  | 
 | 
                    }  | 
 | 
                    if (!dst.hasRemaining())  | 
 | 
                        return CoderResult.OVERFLOW;  | 
 | 
 | 
 | 
                    switch (currentState){ | 
 | 
                        case ASCII:  | 
 | 
                            dst.put((char)(b1 & 0xff));  | 
 | 
                            break;  | 
 | 
                        case JISX0201_1976:  | 
 | 
                            switch (b1) { | 
 | 
                              case 0x5c:    | 
 | 
                                dst.put('\u00a5'); | 
 | 
                                break;  | 
 | 
                              case 0x7e:  | 
 | 
                                dst.put('\u203e'); | 
 | 
                                break;  | 
 | 
                              default:  | 
 | 
                                dst.put((char)b1);  | 
 | 
                                break;  | 
 | 
                            }  | 
 | 
                            break;  | 
 | 
                        case JISX0208_1978:  | 
 | 
                        case JISX0208_1983:  | 
 | 
                            if (!src.hasRemaining())  | 
 | 
                                return CoderResult.UNDERFLOW;  | 
 | 
                            b2 = src.get() & 0xff;  | 
 | 
                            inputSize++;  | 
 | 
                            c = dec0208.decodeDouble(b1,b2);  | 
 | 
                            if (c == UNMAPPABLE_DECODING)  | 
 | 
                                return CoderResult.unmappableForLength(inputSize);  | 
 | 
                            dst.put(c);  | 
 | 
                            break;  | 
 | 
                        case JISX0212_1990:  | 
 | 
                            if (!src.hasRemaining())  | 
 | 
                                return CoderResult.UNDERFLOW;  | 
 | 
                            b2 = src.get() & 0xff;  | 
 | 
                            inputSize++;  | 
 | 
                            c = dec0212.decodeDouble(b1,b2);  | 
 | 
                            if (c == UNMAPPABLE_DECODING)  | 
 | 
                                return CoderResult.unmappableForLength(inputSize);  | 
 | 
                            dst.put(c);  | 
 | 
                            break;  | 
 | 
                        case JISX0201_1976_KANA:  | 
 | 
                        case SHIFTOUT:  | 
 | 
                            if (b1 > 0x5f) { | 
 | 
                                return CoderResult.malformedForLength(inputSize);  | 
 | 
                            }  | 
 | 
                            dst.put((char)(b1 + 0xff40));  | 
 | 
                            break;  | 
 | 
                    }  | 
 | 
                    mark += inputSize;  | 
 | 
                }  | 
 | 
                return CoderResult.UNDERFLOW;  | 
 | 
            } finally { | 
 | 
                src.position(mark);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) { | 
 | 
            if (src.hasArray() && dst.hasArray())  | 
 | 
                return decodeArrayLoop(src, dst);  | 
 | 
            else  | 
 | 
                return decodeBufferLoop(src, dst);  | 
 | 
        }  | 
 | 
 | 
 | 
        public CoderResult implFlush(CharBuffer out) { | 
 | 
            return super.implFlush(out);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    static class Encoder extends CharsetEncoder { | 
 | 
 | 
 | 
        final static DoubleByte.Encoder ENC0208 =  | 
 | 
            (DoubleByte.Encoder)new JIS_X_0208().newEncoder();  | 
 | 
 | 
 | 
        private static byte[] repl = { (byte)0x21, (byte)0x29 }; | 
 | 
        private int currentMode = ASCII;  | 
 | 
        private int replaceMode = JISX0208_1983;  | 
 | 
        private DoubleByte.Encoder enc0208;  | 
 | 
        private DoubleByte.Encoder enc0212;  | 
 | 
        private boolean doSBKANA;  | 
 | 
 | 
 | 
        private Encoder(Charset cs) { | 
 | 
            this(cs, ENC0208, null, true);  | 
 | 
        }  | 
 | 
 | 
 | 
        Encoder(Charset cs,  | 
 | 
                DoubleByte.Encoder enc0208,  | 
 | 
                DoubleByte.Encoder enc0212,  | 
 | 
                boolean doSBKANA) { | 
 | 
            super(cs, 4.0f, (enc0212 != null)? 9.0f : 8.0f, repl);  | 
 | 
            this.enc0208 = enc0208;  | 
 | 
            this.enc0212 = enc0212;  | 
 | 
            this.doSBKANA = doSBKANA;  | 
 | 
        }  | 
 | 
 | 
 | 
        protected int encodeSingle(char inputChar) { | 
 | 
            return -1;  | 
 | 
        }  | 
 | 
 | 
 | 
        protected void implReset() { | 
 | 
            currentMode = ASCII;  | 
 | 
        }  | 
 | 
 | 
 | 
        protected void implReplaceWith(byte[] newReplacement) { | 
 | 
              | 
 | 
 | 
 | 
 | 
 | 
             */  | 
 | 
            if (newReplacement.length == 1) { | 
 | 
                replaceMode = ASCII;  | 
 | 
            } else if (newReplacement.length == 2) { | 
 | 
                replaceMode = JISX0208_1983;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        protected CoderResult implFlush(ByteBuffer out) { | 
 | 
            if (currentMode != ASCII) { | 
 | 
                if (out.remaining() < 3)  | 
 | 
                    return CoderResult.OVERFLOW;  | 
 | 
                out.put((byte)0x1b);  | 
 | 
                out.put((byte)0x28);  | 
 | 
                out.put((byte)0x42);  | 
 | 
                currentMode = ASCII;  | 
 | 
            }  | 
 | 
            return CoderResult.UNDERFLOW;  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean canEncode(char c) { | 
 | 
            return ((c <= '\u007F') ||  | 
 | 
                    (c >= 0xFF61 && c <= 0xFF9F) ||  | 
 | 
                    (c == '\u00A5') ||  | 
 | 
                    (c == '\u203E') ||  | 
 | 
                    enc0208.canEncode(c) ||  | 
 | 
                    (enc0212!=null && enc0212.canEncode(c)));  | 
 | 
        }  | 
 | 
 | 
 | 
        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 <= '\u007F') { | 
 | 
                        if (currentMode != ASCII) { | 
 | 
                            if (dl - dp < 3)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            da[dp++] = (byte)0x1b;  | 
 | 
                            da[dp++] = (byte)0x28;  | 
 | 
                            da[dp++] = (byte)0x42;  | 
 | 
                            currentMode = ASCII;  | 
 | 
                        }  | 
 | 
                        if (dl - dp < 1)  | 
 | 
                            return CoderResult.OVERFLOW;  | 
 | 
                        da[dp++] = (byte)c;  | 
 | 
                    } else if (c >= 0xff61 && c <= 0xff9f && doSBKANA) { | 
 | 
                          | 
 | 
                        if (currentMode != JISX0201_1976_KANA) { | 
 | 
                            if (dl - dp < 3)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            da[dp++] = (byte)0x1b;  | 
 | 
                            da[dp++] = (byte)0x28;  | 
 | 
                            da[dp++] = (byte)0x49;  | 
 | 
                            currentMode = JISX0201_1976_KANA;  | 
 | 
                        }  | 
 | 
                        if (dl - dp < 1)  | 
 | 
                            return CoderResult.OVERFLOW;  | 
 | 
                        da[dp++] = (byte)(c - 0xff40);  | 
 | 
                    } else if (c == '\u00A5' || c == '\u203E') { | 
 | 
                          | 
 | 
                        if (currentMode != JISX0201_1976) { | 
 | 
                            if (dl - dp < 3)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            da[dp++] = (byte)0x1b;  | 
 | 
                            da[dp++] = (byte)0x28;  | 
 | 
                            da[dp++] = (byte)0x4a;  | 
 | 
                            currentMode = JISX0201_1976;  | 
 | 
                        }  | 
 | 
                        if (dl - dp < 1)  | 
 | 
                            return CoderResult.OVERFLOW;  | 
 | 
                        da[dp++] = (c == '\u00A5')?(byte)0x5C:(byte)0x7e;  | 
 | 
                    } else { | 
 | 
                        int index = enc0208.encodeChar(c);  | 
 | 
                        if (index != UNMAPPABLE_ENCODING) { | 
 | 
                            if (currentMode != JISX0208_1983) { | 
 | 
                                if (dl - dp < 3)  | 
 | 
                                    return CoderResult.OVERFLOW;  | 
 | 
                                da[dp++] = (byte)0x1b;  | 
 | 
                                da[dp++] = (byte)0x24;  | 
 | 
                                da[dp++] = (byte)0x42;  | 
 | 
                                currentMode = JISX0208_1983;  | 
 | 
                            }  | 
 | 
                            if (dl - dp < 2)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            da[dp++] = (byte)(index >> 8);  | 
 | 
                            da[dp++] = (byte)(index & 0xff);  | 
 | 
                        } else if (enc0212 != null &&  | 
 | 
                                   (index = enc0212.encodeChar(c)) != UNMAPPABLE_ENCODING) { | 
 | 
                            if (currentMode != JISX0212_1990) { | 
 | 
                                if (dl - dp < 4)  | 
 | 
                                    return CoderResult.OVERFLOW;  | 
 | 
                                da[dp++] = (byte)0x1b;  | 
 | 
                                da[dp++] = (byte)0x24;  | 
 | 
                                da[dp++] = (byte)0x28;  | 
 | 
                                da[dp++] = (byte)0x44;  | 
 | 
                                currentMode = JISX0212_1990;  | 
 | 
                            }  | 
 | 
                            if (dl - dp < 2)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            da[dp++] = (byte)(index >> 8);  | 
 | 
                            da[dp++] = (byte)(index & 0xff);  | 
 | 
                        } else { | 
 | 
                            if (Character.isSurrogate(c) && sgp.parse(c, sa, sp, sl) < 0)  | 
 | 
                                return sgp.error();  | 
 | 
                            if (unmappableCharacterAction()  | 
 | 
                                == CodingErrorAction.REPLACE  | 
 | 
                                && currentMode != replaceMode) { | 
 | 
                                if (dl - dp < 3)  | 
 | 
                                    return CoderResult.OVERFLOW;  | 
 | 
                                if (replaceMode == ASCII) { | 
 | 
                                    da[dp++] = (byte)0x1b;  | 
 | 
                                    da[dp++] = (byte)0x28;  | 
 | 
                                    da[dp++] = (byte)0x42;  | 
 | 
                                } else { | 
 | 
                                    da[dp++] = (byte)0x1b;  | 
 | 
                                    da[dp++] = (byte)0x24;  | 
 | 
                                    da[dp++] = (byte)0x42;  | 
 | 
                                }  | 
 | 
                                currentMode = replaceMode;  | 
 | 
                            }  | 
 | 
                            if (Character.isSurrogate(c))  | 
 | 
                                return sgp.unmappableResult();  | 
 | 
                            return CoderResult.unmappableForLength(1);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    sp++;  | 
 | 
                }  | 
 | 
                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 <= '\u007F') { | 
 | 
                        if (currentMode != ASCII) { | 
 | 
                            if (dst.remaining() < 3)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            dst.put((byte)0x1b);  | 
 | 
                            dst.put((byte)0x28);  | 
 | 
                            dst.put((byte)0x42);  | 
 | 
                            currentMode = ASCII;  | 
 | 
                        }  | 
 | 
                        if (dst.remaining() < 1)  | 
 | 
                            return CoderResult.OVERFLOW;  | 
 | 
                        dst.put((byte)c);  | 
 | 
                    } else if (c >= 0xff61 && c <= 0xff9f && doSBKANA) { | 
 | 
                          | 
 | 
                        if (currentMode != JISX0201_1976_KANA) { | 
 | 
                            if (dst.remaining() < 3)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            dst.put((byte)0x1b);  | 
 | 
                            dst.put((byte)0x28);  | 
 | 
                            dst.put((byte)0x49);  | 
 | 
                            currentMode = JISX0201_1976_KANA;  | 
 | 
                        }  | 
 | 
                        if (dst.remaining() < 1)  | 
 | 
                            return CoderResult.OVERFLOW;  | 
 | 
                        dst.put((byte)(c - 0xff40));  | 
 | 
                    } else if (c == '\u00a5' || c == '\u203E') { | 
 | 
                        if (currentMode != JISX0201_1976) { | 
 | 
                            if (dst.remaining() < 3)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            dst.put((byte)0x1b);  | 
 | 
                            dst.put((byte)0x28);  | 
 | 
                            dst.put((byte)0x4a);  | 
 | 
                            currentMode = JISX0201_1976;  | 
 | 
                        }  | 
 | 
                        if (dst.remaining() < 1)  | 
 | 
                            return CoderResult.OVERFLOW;  | 
 | 
                        dst.put((c == '\u00A5')?(byte)0x5C:(byte)0x7e);  | 
 | 
                    } else { | 
 | 
                        int index = enc0208.encodeChar(c);  | 
 | 
                        if (index != UNMAPPABLE_ENCODING) { | 
 | 
                            if (currentMode != JISX0208_1983) { | 
 | 
                                if (dst.remaining() < 3)  | 
 | 
                                    return CoderResult.OVERFLOW;  | 
 | 
                                dst.put((byte)0x1b);  | 
 | 
                                dst.put((byte)0x24);  | 
 | 
                                dst.put((byte)0x42);  | 
 | 
                                currentMode = JISX0208_1983;  | 
 | 
                            }  | 
 | 
                            if (dst.remaining() < 2)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            dst.put((byte)(index >> 8));  | 
 | 
                            dst.put((byte)(index & 0xff));  | 
 | 
                        } else if (enc0212 != null &&  | 
 | 
                                   (index = enc0212.encodeChar(c)) != UNMAPPABLE_ENCODING) { | 
 | 
                            if (currentMode != JISX0212_1990) { | 
 | 
                                if (dst.remaining() < 4)  | 
 | 
                                    return CoderResult.OVERFLOW;  | 
 | 
                                dst.put((byte)0x1b);  | 
 | 
                                dst.put((byte)0x24);  | 
 | 
                                dst.put((byte)0x28);  | 
 | 
                                dst.put((byte)0x44);  | 
 | 
                                currentMode = JISX0212_1990;  | 
 | 
                            }  | 
 | 
                            if (dst.remaining() < 2)  | 
 | 
                                return CoderResult.OVERFLOW;  | 
 | 
                            dst.put((byte)(index >> 8));  | 
 | 
                            dst.put((byte)(index & 0xff));  | 
 | 
                        } else { | 
 | 
                            if (Character.isSurrogate(c) && sgp.parse(c, src) < 0)  | 
 | 
                                return sgp.error();  | 
 | 
                            if (unmappableCharacterAction() == CodingErrorAction.REPLACE  | 
 | 
                                && currentMode != replaceMode) { | 
 | 
                                if (dst.remaining() < 3)  | 
 | 
                                    return CoderResult.OVERFLOW;  | 
 | 
                                if (replaceMode == ASCII) { | 
 | 
                                    dst.put((byte)0x1b);  | 
 | 
                                    dst.put((byte)0x28);  | 
 | 
                                    dst.put((byte)0x42);  | 
 | 
                                } else { | 
 | 
                                    dst.put((byte)0x1b);  | 
 | 
                                    dst.put((byte)0x24);  | 
 | 
                                    dst.put((byte)0x42);  | 
 | 
                                }  | 
 | 
                                currentMode = replaceMode;  | 
 | 
                            }  | 
 | 
                            if (Character.isSurrogate(c))  | 
 | 
                                return sgp.unmappableResult();  | 
 | 
                            return CoderResult.unmappableForLength(1);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    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);  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |