12d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// © 2016 and later: Unicode, Inc. and others.
22d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html#License
37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
5bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert * Copyright (C) 2008-2015, International Business Machines Corporation and
67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved.
77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert *******************************************************************************
87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */
97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.charset;
107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.ByteBuffer;
127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.CharBuffer;
137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.IntBuffer;
147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.charset.CharsetDecoder;
157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.charset.CharsetEncoder;
167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.nio.charset.CoderResult;
177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.util.Arrays;
187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.charset.CharsetMBCS.CharsetDecoderMBCS;
207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.charset.CharsetMBCS.CharsetEncoderMBCS;
217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter;
227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UTF16;
237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.text.UnicodeSet;
247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertclass CharsetISO2022 extends CharsetICU {
267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private UConverterDataISO2022 myConverterData;
277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private int variant;           // one of enum {ISO_2022_JP, ISO_2022_KR, or ISO_2022_CN}
282d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte[] SHIFT_IN_STR    = { 0x0f };
307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//    private static final byte[] SHIFT_OUT_STR   = { 0x0e };
317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte CR    = 0x0D;
337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte LF    = 0x0A;
347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte H_TAB = 0x09;
367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte SPACE = 0x20;
377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char HWKANA_START  = 0xff61;
397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char HWKANA_END    = 0xff9f;
402d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 94-character sets with native byte values A1..FE are encoded in ISO 2022
437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * as bytes 21..7E. (Subtract 0x80.)
447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 96-character  sets with native bit values A0..FF are encoded in ISO 2022
457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * as bytes 20..7F. (Subtract 0x80.)
467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Do not encode C1 control codes with native bytes 80..9F
477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * as bytes 00..1F (C0 control codes).
487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char GR94_START    = 0xa1;
517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char GR94_END      = 0xfe;
527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char GR96_START    = 0xa0;
547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final char GR96_END      = 0xff;
552d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* for ISO-2022-JP and -CN implementations */
577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // typedef enum {
587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* shared values */
597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte INVALID_STATE = -1;
607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte ASCII         = 0;
612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte SS2_STATE = 0x10;
637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte SS3_STATE = 0x11;
642d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* JP */
667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte ISO8859_1 = 1;
677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte ISO8859_7 = 2;
687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte JISX201   = 3;
697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte JISX208   = 4;
707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte JISX212   = 5;
717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte GB2312    = 6;
727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte KSC5601   = 7;
737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte HWKANA_7BIT  = 8; /* Halfwidth Katakana 7 bit */
742d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* CN */
767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* the first few enum constants must keep their values because they corresponds to myConverterArray[] */
777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte GB2312_1  = 1;
787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte ISO_IR_165= 2;
797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643 = 3;
802d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * these are used in StateEnum and ISO2022State variables,
837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * but CNS_11643 must be used to index into myConverterArray[]
847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_0 = 0x20;
867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_1 = 0x21;
877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_2 = 0x22;
887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_3 = 0x23;
897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_4 = 0x24;
907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_5 = 0x25;
917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_6 = 0x26;
927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte CNS_11643_7 = 0x27;
937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // } StateEnum;
942d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CharsetISO2022(String icuCanonicalName, String javaCanonicalName, String[] aliases) {
977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        super(icuCanonicalName, javaCanonicalName, aliases);
982d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData = new UConverterDataISO2022();
1002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int versionIndex = icuCanonicalName.indexOf("version=");
1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int version = Integer.decode(icuCanonicalName.substring(versionIndex+8, versionIndex+9)).intValue();
1032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.version = version;
1052d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (icuCanonicalName.indexOf("locale=ja") > 0) {
1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ISO2022InitJP(version);
1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (icuCanonicalName.indexOf("locale=zh") > 0) {
1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ISO2022InitCN(version);
1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else /* if (icuCanonicalName.indexOf("locale=ko") > 0) */ {
1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ISO2022InitKR(version);
1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.currentEncoder = (CharsetEncoderMBCS)myConverterData.currentConverter.newEncoder();
1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.currentDecoder = (CharsetDecoderMBCS)myConverterData.currentConverter.newDecoder();
1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void ISO2022InitJP(int version) {
1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        variant = ISO_2022_JP;
1202d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxBytesPerChar = 6;
1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        minBytesPerChar = 1;
1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxCharsPerByte = 1;
1242d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        // open the required converters and cache them
1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if((jpCharsetMasks[version]&CSM(ISO8859_7)) != 0) {
1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.myConverterArray[ISO8859_7] = ((CharsetMBCS)CharsetICU.forNameICU("ISO8859_7")).sharedData;
1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // myConverterData.myConverterArray[JISX201] = ((CharsetMBCS)CharsetICU.forNameICU("jisx-201")).sharedData;
1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.myConverterArray[JISX208] = ((CharsetMBCS)CharsetICU.forNameICU("Shift-JIS")).sharedData;
1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if ((jpCharsetMasks[version]&CSM(JISX212)) != 0) {
1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.myConverterArray[JISX212] = ((CharsetMBCS)CharsetICU.forNameICU("jisx-212")).sharedData;
1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if ((jpCharsetMasks[version]&CSM(GB2312)) != 0) {
1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.myConverterArray[GB2312] = ((CharsetMBCS)CharsetICU.forNameICU("ibm-5478")).sharedData;
1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if ((jpCharsetMasks[version]&CSM(KSC5601)) != 0) {
1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.myConverterArray[KSC5601] = ((CharsetMBCS)CharsetICU.forNameICU("ksc_5601")).sharedData;
1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1392d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // create a generic CharsetMBCS object
1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.currentConverter = (CharsetMBCS)CharsetICU.forNameICU("icu-internal-25546");
1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1432d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void ISO2022InitCN(int version) {
1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        variant = ISO_2022_CN;
1462d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxBytesPerChar = 8;
1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        minBytesPerChar = 1;
1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxCharsPerByte = 1;
1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // open the required coverters and cache them.
1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.myConverterArray[GB2312_1] = ((CharsetMBCS)CharsetICU.forNameICU("ibm-5478")).sharedData;
1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (version == 1) {
1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.myConverterArray[ISO_IR_165] = ((CharsetMBCS)CharsetICU.forNameICU("iso-ir-165")).sharedData;
1542d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        }
1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.myConverterArray[CNS_11643] = ((CharsetMBCS)CharsetICU.forNameICU("cns-11643-1992")).sharedData;
1562d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        // create a generic CharsetMBCS object
1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.currentConverter = (CharsetMBCS)CharsetICU.forNameICU("icu-internal-25546");
1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void ISO2022InitKR(int version) {
1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        variant = ISO_2022_KR;
1632d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16487255a3fc79cc94374b5b8adc76a86e251ac7d3eFredrik Roubert        maxBytesPerChar = 8;
1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        minBytesPerChar = 1;
1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        maxCharsPerByte = 1;
1672d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (version == 1) {
1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentConverter = (CharsetMBCS)CharsetICU.forNameICU("icu-internal-25546");
1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentConverter.subChar1 = fromUSubstitutionChar[0][0];
1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentConverter = (CharsetMBCS)CharsetICU.forNameICU("ibm-949");
1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
1742d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.currentEncoder = (CharsetEncoderMBCS)myConverterData.currentConverter.newEncoder();
1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.currentDecoder = (CharsetDecoderMBCS)myConverterData.currentConverter.newDecoder();
1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * ISO 2022 control codes must not be converted from Unicode
1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * because they would mess up the byte stream.
1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The bit mask 0x0800c000 has bits set at bit positions 0xe, 0xf, 0x1b
1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * corresponding to SO, SI, and ESC.
1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1852d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    private static boolean IS_2022_CONTROL(int c) {
1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (c<0x20) && (((1<<c) & 0x0800c000) != 0);
1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
1882d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Check that the result is a 2-byte value with each byte in the range A1..FE
1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * (strict EUC DBCS) before accepting it and subtracting 0x80 from each byte
1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * to move it to the ISO 2022 range 21..7E.
1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * return 0 if out of range.
1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int _2022FromGR94DBCS(int value) {
1962d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        if ((value <= 0xfefe && value >= 0xa1a1) &&
1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ((short)(value&UConverterConstants.UNSIGNED_BYTE_MASK) <= 0xfe && ((short)(value&UConverterConstants.UNSIGNED_BYTE_MASK) >= 0xa1))) {
1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (value - 0x8080); /* shift down to 21..7e byte range */
1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 0; /* not valid for ISO 2022 */
2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
2052d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     * Commented out because Ticket 5691: Call sites now check for validity. They can just += 0x8080 after that.
2062d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This method does the reverse of _2022FromGR94DBCS(). Given the 2022 code point, it returns the
2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * 2 byte value that is in the range A1..FE for each byte. Otherwise it returns the 2022 code point
2092d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     * unchanged.
2102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int _2022ToGR94DBCS(int value) {
2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int returnValue = value + 0x8080;
2132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2142d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        if ((returnValue <= 0xfefe && returnValue >= 0xa1a1) &&
2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ((short)(returnValue&UConverterConstants.UNSIGNED_BYTE_MASK) <= 0xfe && ((short)(returnValue&UConverterConstants.UNSIGNED_BYTE_MASK) >= 0xa1))) {
2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return returnValue;
2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return value;
2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }*/
2212d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* is the StateEnum charset value for a DBCS charset? */
2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static boolean IS_JP_DBCS(byte cs) {
2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return ((JISX208 <= cs) && (cs <= KSC5601));
2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2262d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static short CSM(short cs) {
2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return (short)(1<<cs);
2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* This gets the valid index of the end of buffer when decoding. */
2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static int getEndOfBuffer_2022(ByteBuffer source) {
2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int sourceIndex = source.position();
2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte mySource = 0;
2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        mySource = source.get(sourceIndex);
2362d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (source.hasRemaining() && mySource != ESC_2022) {
2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            mySource = source.get();
2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (mySource == ESC_2022) {
2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            sourceIndex++;
2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return sourceIndex;
2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2462d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * This is a simple version of _MBCSGetNextUChar() calls the method in CharsetDecoderMBCS and returns
2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * the value given.
2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *
2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Return value:
2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * U+fffe   unassigned
2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * U+ffff   illegal
2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * otherwise the Unicode code point
2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     private int MBCSSimpleGetNextUChar(UConverterSharedData sharedData,
2572d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                               ByteBuffer   source,
2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                               boolean      useFallback) {
2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         int returnValue;
2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         UConverterSharedData tempSharedData = myConverterData.currentConverter.sharedData;
2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         myConverterData.currentConverter.sharedData = sharedData;
2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         returnValue = myConverterData.currentDecoder.simpleGetNextUChar(source, useFallback);
2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         myConverterData.currentConverter.sharedData = tempSharedData;
2642d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         return returnValue;
2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @param is the the output byte
2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * @return 1 roundtrip byte  0 no mapping  -1 fallback byte
2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    static int MBCSSingleFromUChar32(UConverterSharedData sharedData, int c, int[] retval, boolean useFallback) {
2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        char[] table;
2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int value;
2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* BMP-only codepages are stored without stage 1 entries for supplementary code points */
2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (c >= 0x10000 && !sharedData.mbcs.hasSupplementary()) {
2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 0;
2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* convert the Unicode code point in c into codepage bytes */
2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        table = sharedData.mbcs.fromUnicodeTable;
2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* get the byte for the output */
2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        value = CharsetMBCS.MBCS_SINGLE_RESULT_FROM_U(table, sharedData.mbcs.fromUnicodeChars, c);
2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* get the byte for the output */
2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        retval[0] = value & 0xff;
2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (value >= 0xf00) {
2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 1; /* roundtrip */
2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (useFallback ? value>=0x800 : value>=0xc00) {
2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return -1; /* fallback taken */
2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return 0; /* no mapping */
2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
2932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Each of these charset masks (with index x) contains a bit for a charset in exact correspondence
2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * to whether that charset is used in the corresponding version x of ISO_2022, locale=ja,version=x
2972d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Note: The converter uses some leniency:
2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * - The escape sequence ESC ( I for half-width 7-bit Katakana is recognized in
3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *   all versions, not just JIS7 and JIS8.
3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * - ICU does not distinguish between different version so of JIS X 0208.
3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final short jpCharsetMasks[] = {
3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        (short)(CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)),
3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        (short)(CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)),
3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        (short)(CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7)),
3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        (short)(CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7)),
3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        (short)(CSM(ASCII)|CSM(JISX201)|CSM(JISX208)|CSM(HWKANA_7BIT)|CSM(JISX212)|CSM(GB2312)|CSM(KSC5601)|CSM(ISO8859_1)|CSM(ISO8859_7))
3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/*
3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // typedef enum {
3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte ASCII1 = 0;
3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte LATIN1 = 1;
3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte SBCS   = 2;
3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte DBCS   = 3;
3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte MBCS   = 4;
3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte HWKANA = 5;
3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // } Cnv2002Type;
3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert*/
3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static class ISO2022State {
3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private byte []cs;  /* Charset number for SI (G0)/SO (G1)/SS2 (G2)/SS3 (G3) */
3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private byte g;     /* 0..3 for G0..G3 (SI/SO/SS2/SS3) */
3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private byte prevG; /* g before single shift (SS2 or SS3) */
3262d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ISO2022State() {
3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cs = new byte[4];
3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        void reset() {
3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            Arrays.fill(cs, (byte)0);
3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            g = 0;
3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            prevG = 0;
3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3372d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//    private static final byte UCNV_OPTIONS_VERSION_MASK = 0xf;
3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte UCNV_2022_MAX_CONVERTERS  = 10;
3402d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static class UConverterDataISO2022 {
3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UConverterSharedData []myConverterArray;
3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CharsetEncoderMBCS currentEncoder;
3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CharsetDecoderMBCS currentDecoder;
3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CharsetMBCS currentConverter;
3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ISO2022State toU2022State;
3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ISO2022State fromU2022State;
3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int key;
3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int version;
3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean isEmptySegment;
3512d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        UConverterDataISO2022() {
3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterArray = new UConverterSharedData[UCNV_2022_MAX_CONVERTERS];
3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            toU2022State = new ISO2022State();
3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromU2022State = new ISO2022State();
3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            key = 0;
3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            version = 0;
3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            isEmptySegment = false;
3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        void reset() {
3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            toU2022State.reset();
3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromU2022State.reset();
3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            isEmptySegment = false;
3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
3672d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static final byte ESC_2022 = 0x1B; /* ESC */
3692d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // typedef enum {
3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte INVALID_2022              = -1; /* Doesn't correspond to a valid iso 2022 escape sequence */
3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte VALID_NON_TERMINAL_2022   =  0;  /* so far corresponds to a valid iso 2022 escape sequence */
3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte VALID_TERMINAL_2022       =  1;  /* corresponds to a valid iso 2022 escape sequence */
3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private static final byte VALID_MAYBE_TERMINAL_2022 =  2;  /* so far matches one iso 2022 escape sequence, but by adding
3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                                     more characters might match another escape sequence */
3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    // } UCNV_TableStates_2022;
3772d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The way these state transition arrays work is:
3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * ex : ESC$B is the sequence for JISX208
3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      a) First Iteration: char is ESC
3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *          i) Get the value of ESC from normalize_esq_chars_2022[] with int value of ESC as index
3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             int x = normalize_esq_chars_2022[27] which is equal to 1
3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         ii) Search for this value in escSeqStateTable_Key_2022[]
3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             value of x is stored at escSeqStateTable_Key_2022[0]
3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *        iii) Save this index as offset
3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         iv) Get state of this sequence from escSeqStateTable_Value_2022[]
3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             escSeqStateTable_value_2022[offset], which is VALID_NON_TERMINAL_2022
3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      b) Switch on this state and continue to next char
3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *          i) Get the value of $ from normalize_esq_chars_2022[] with int value of $ as index
3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             which is normalize_esq_chars_2022[36] == 4
3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         ii) x is currently 1(from above)
3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             x<<=5 -- x is now 32
3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             x+=normalize_esq_chars_2022[36]
3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             now x is 36
3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *        iii) Search for this value in escSeqStateTable_Key_2022[]
3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             value of x is stored at escSeqStateTable_Key_2022[2], so offset is 2
3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         iv) Get state of this sequence from escSeqStateTable_Value_2022[]
3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             escSeqStateTable_Value_2022[offset], which is VALID_NON_TERMINAL_2022
4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      c) Switch on this state and continue to next char
4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *          i) Get the value of B from normalize_esq_chars_2022[] with int value of B as index
4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         ii) x is currently 36 (from above)
4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             x<<=5 -- x is now 1152
4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             x+= normalize_esq_chars_2022[66]
4057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             now x is 1161
4067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *        iii) Search for this value in escSeqStateTable_Key_2022[]
4077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             value of x is stored at escSeqStateTable_Key_2022[21], so offset is 21
4087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *         iv) Get state of this sequence from escSeqStateTable_Value_2022[1]
4097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *             escSeqStateTable_Value_2022[offset], which is VALID_TERMINAL_2022
4107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *          v) Get the converter name from escSeqStateTable_Result_2022[21] which is JISX208
4117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
4127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     /* Below are the 3 arrays depicting a state transition table */
4137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     private static final byte normalize_esq_chars_2022[] = {
4147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         /* 0       1       2       3       4       5       6       7       8       9 */
4157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      1,      0,      0,
4187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      4,      7,     29,      0,
4197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            2,     24,     26,     27,      0,      3,     23,      6,      0,      0,
4207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      5,      8,      9,     10,     11,     12,
4227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           13,     14,     15,     16,     17,     18,     19,     20,     25,     28,
4237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,     21,      0,      0,      0,      0,      0,      0,      0,
4247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           22,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0,      0,      0,      0,      0,
4417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            0,      0,      0,      0,      0,      0
4427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     };
4432d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
4447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     private static final short MAX_STATES_2022 = 74;
4457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     private static final int escSeqStateTable_Key_2022[/* MAX_STATES_2022 */] = {
4467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         /* 0        1          2         3        4          5         6         7         8         9 */
4477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            1,      34,        36,       39,      55,        57,       60,       61,     1093,     1096,
4487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         1097,    1098,      1099,     1100,     1101,     1102,     1103,     1104,     1105,     1106,
4497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         1109,    1154,      1157,     1160,     1161,     1176,     1178,     1179,     1254,     1257,
4507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         1768,    1773,      1957,    35105,    36933,    36936,    36937,    36938,    36939,    36940,
4517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        36942,   36943,     36944,    36945,    36946,    36947,    36948,    37640,    37642,    37644,
4527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        37646,   37711,     37744,    37745,    37746,    37747,    37748,    40133,    40136,    40138,
4537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        40139,   40140,     40141,  1123363, 35947624, 35947625, 35947626, 35947627, 35947629, 35947630,
4547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     35947631, 35947635, 35947636, 35947638
4557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     };
4562d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
4577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     private static final byte escSeqStateTable_Value_2022[/* MAX_STATES_2022 */] = {
4587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         /*         0                           1                           2                           3                       4               */
4592d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert         VALID_NON_TERMINAL_2022,   VALID_NON_TERMINAL_2022,    VALID_NON_TERMINAL_2022,    VALID_NON_TERMINAL_2022,    VALID_NON_TERMINAL_2022,
4607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,    VALID_NON_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert       VALID_MAYBE_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,   VALID_NON_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         VALID_NON_TERMINAL_2022,   VALID_NON_TERMINAL_2022,    VALID_NON_TERMINAL_2022,    VALID_NON_TERMINAL_2022,        VALID_TERMINAL_2022,
4657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,    VALID_NON_TERMINAL_2022,        VALID_TERMINAL_2022,
4667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,    VALID_NON_TERMINAL_2022,        VALID_TERMINAL_2022,
4727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022,
4737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             VALID_TERMINAL_2022,       VALID_TERMINAL_2022,        VALID_TERMINAL_2022,        VALID_TERMINAL_2022
4747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     };
4752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
4767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     /* Type def for refactoring changeState_2022 code */
4777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     // typedef enum {
4787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         private static final byte ISO_2022_JP = 1;
4797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         private static final byte ISO_2022_KR = 2;
4807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         private static final byte ISO_2022_CN = 3;
4817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     // } Variant2022;
4822d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
4837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* const UConverterSharedData _ISO2022Data; */
4847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //private UConverterSharedData _ISO2022JPData;
4857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //private UConverterSharedData _ISO2022KRData;
4867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    //private UConverterSharedData _ISO2022CNData;
4872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
4887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /******************** to unicode ********************/
4897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /****************************************************
4907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Recognized escape sequenes are
4917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>(B  ASCII
4927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>.A  ISO-8859-1
4937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>.F  ISO-8859-7
4947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>(J  JISX-201
4957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>(I  JISX-201
4967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>$B  JISX-208
4977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>$@  JISX-208
4987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>$(D JISX-212
4997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>$A  GB2312
5007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * <ESC>$(C KSC5601
5017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
5027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte nextStateToUnicodeJP[/* MAX_STATES_2022 */] = {
5037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*     0               1               2               3               4               5               6               7               8               9    */
5047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,      SS2_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ASCII,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,        JISX201,    HWKANA_7BIT,        JISX201,  INVALID_STATE,
5067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,        JISX208,         GB2312,        JISX208,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ISO8859_1,      ISO8859_7,        JISX208,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,        KSC5601,        JISX212,  INVALID_STATE,
5087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE
5127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
5132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte nextStateToUnicodeCN[/* MAX_STATES_2022 */] = {
5157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*     0               1               2               3               4               5               6               7               8               9    */
5167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,      SS2_STATE,      SS3_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,       GB2312_1,  INVALID_STATE,     ISO_IR_165,
5217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          CNS_11643_1,    CNS_11643_2,    CNS_11643_3,    CNS_11643_4,    CNS_11643_5,    CNS_11643_6,    CNS_11643_7,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE,
5237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        INVALID_STATE,  INVALID_STATE,  INVALID_STATE,  INVALID_STATE
5247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
5252d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* runs through a state machine to determine the escape sequence - codepage correspondence */
5277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    @SuppressWarnings("fallthrough")
5287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private CoderResult changeState_2022(CharsetDecoderICU decoder, ByteBuffer source, int var) {
5297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CoderResult err = CoderResult.UNDERFLOW;
5307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        boolean DONE = false;
5317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte value;
5327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int key[] = {myConverterData.key};
5337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int offset[] = {0};
5347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int initialToULength = decoder.toULength;
5357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        byte c;
5367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int malformLength = 0;
5372d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        value = VALID_NON_TERMINAL_2022;
5397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (source.hasRemaining()) {
5407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            c = source.get();
5417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            malformLength++;
5427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            decoder.toUBytesArray[decoder.toULength++] = c;
5437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            value = getKey_2022(c, key, offset);
5442d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch(value) {
5462d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case VALID_NON_TERMINAL_2022:
5487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with the loop */
5497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
5502d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case VALID_TERMINAL_2022:
5527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                key[0] = 0;
5537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                DONE = true;
5547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
5552d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case INVALID_2022:
5577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                DONE = true;
5587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
5592d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case VALID_MAYBE_TERMINAL_2022:
5617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* not ISO_2022 itself, finish here */
5627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                value = VALID_TERMINAL_2022;
5637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                key[0] = 0;
5647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                DONE = true;
5657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
5667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
5677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (DONE) {
5687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
5697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
5707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
5717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// DONE:
5727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        myConverterData.key = key[0];
5732d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
5747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (value == VALID_NON_TERMINAL_2022) {
5757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* indicate that the escape sequence is incomplete: key !=0 */
5767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
5777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (value == INVALID_2022) {
5787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            err = CoderResult.malformedForLength(malformLength);
5797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else /* value == VALID_TERMINAL_2022 */ {
5807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            switch (var) {
5817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case ISO_2022_JP: {
5827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte tempState = nextStateToUnicodeJP[offset[0]];
5837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                switch (tempState) {
5847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case INVALID_STATE:
5857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.malformedForLength(malformLength);
5867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
5877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case SS2_STATE:
5887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.toU2022State.cs[2] != 0) {
5897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.toU2022State.g < 2) {
5907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.prevG = myConverterData.toU2022State.g;
5917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
5927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 2;
5932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    } else {
5947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* illegal to have SS2 before a matching designator */
5957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.malformedForLength(malformLength);
5967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
5977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
5987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* case SS3_STATE: not used in ISO-2022-JP-x */
5997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case ISO8859_1:
6007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case ISO8859_7:
6017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if ((jpCharsetMasks[myConverterData.version] & CSM(tempState)) == 0) {
6027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.unmappableForLength(malformLength);
6037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
6047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* G2 charset for SS2 */
6057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.cs[2] = tempState;
6067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
6077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                default:
6097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if ((jpCharsetMasks[myConverterData.version] & CSM(tempState)) == 0) {
6107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.unmappableForLength(source.position() - 1);
6117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
6127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* G0 charset */
6137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.cs[0] = tempState;
6147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
6157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } // end of switch
6177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
6187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
6197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case ISO_2022_CN: {
6207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte tempState = nextStateToUnicodeCN[offset[0]];
6217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                switch (tempState) {
6227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case INVALID_STATE:
6237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.unmappableForLength(malformLength);
6247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case SS2_STATE:
6267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.toU2022State.cs[2] != 0) {
6277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.toU2022State.g < 2) {
6287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.prevG = myConverterData.toU2022State.g;
6297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
6307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 2;
6317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
6327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* illegal to have SS2 before a matching designator */
6337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.malformedForLength(malformLength);
6347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
6357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case SS3_STATE:
6377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.toU2022State.cs[3] != 0) {
6387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.toU2022State.g < 2) {
6397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.prevG = myConverterData.toU2022State.g;
6407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
6417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 3;
6427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
6437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* illegal to have SS3 before a matching designator */
6447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.malformedForLength(malformLength);
6457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
6467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case ISO_IR_165:
6487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.version == 0) {
6497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.unmappableForLength(malformLength);
6507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
6517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
6527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* fall through */
6537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case GB2312_1:
6547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* fall through */
6557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case CNS_11643_1:
6567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.toU2022State.cs[1] = tempState;
6577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                case CNS_11643_2:
6597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.toU2022State.cs[2] = tempState;
6607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                default:
6627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* other CNS 11643 planes */
6637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.version == 0) {
6647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.unmappableForLength(source.position() - 1);
6657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
6667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.cs[3] = tempState;
6677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
6687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
6697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } //end of switch
6707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
6717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
6727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            case ISO_2022_KR:
6737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (offset[0] == 0x30) {
6747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* nothing to be done, just accept this one escape sequence */
6757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
6767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.unmappableForLength(malformLength);
6777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
6787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
6797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            default:
6807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = CoderResult.malformedForLength(malformLength);
6817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
6827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } // end of switch
6837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
6847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (!err.isError()) {
6857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            decoder.toULength = 0;
6867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else if (err.isMalformed()) {
6877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (decoder.toULength > 1) {
6887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /*
6897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 * Ticket 5691: consistent illegal sequences:
6907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 * - We include at least the first byte (ESC) in the illegal sequence.
6917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 * - If any of the non-initial bytes could be the start of a character,
6927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 *   we stop the illegal sequece before the first one of those.
6937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 *   In escape sequences, all following bytes are "printable", that is,
6947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 *   unless they are completely illegal (>7f in SBCS, outside 21..7e in DBCS),
6957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 *   they are valid single/lead bytes.
6967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 *   For simplicity, we always only report the initial ESC byte as the
6977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 *   illegal sequence and back out all other bytes we looked at.
6987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                 */
6997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* Back out some bytes. */
7007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int backOutDistance = decoder.toULength - 1;
7017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int bytesFromThisBuffer = decoder.toULength - initialToULength;
7027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (backOutDistance <= bytesFromThisBuffer) {
7037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* same as initialToULength<=1 */
7047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    source.position(source.position() - backOutDistance);
7057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
7067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* Back out bytes from the previous buffer: Need to replay them. */
7077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    decoder.preToULength = (byte)(bytesFromThisBuffer - backOutDistance);
7087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* same as -(initalToULength-1) */
7097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* preToULength is negative! */
7107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for (int i = 0; i < -(decoder.preToULength); i++) {
7117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        decoder.preToUArray[i] = decoder.toUBytesArray[i+1];
7127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
7137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    source.position(source.position() - bytesFromThisBuffer);
7147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
7157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                decoder.toULength = 1;
7167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
7177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return err;
7207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7212d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static byte getKey_2022(byte c, int[]key, int[]offset) {
7237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int togo;
7247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int low = 0;
7257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int hi = MAX_STATES_2022;
7267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int oldmid = 0;
7272d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7282d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        togo = normalize_esq_chars_2022[c&UConverterConstants.UNSIGNED_BYTE_MASK];
7292d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (togo == 0) {
7317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* not a valid character anywhere in an escape sequence */
7327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            key[0] = 0;
7337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            offset[0] = 0;
7347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return INVALID_2022;
7357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        togo = (key[0] << 5) + togo;
7372d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        while (hi != low) { /* binary search */
7397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mid = (hi+low) >> 1; /* Finds median */
7402d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (mid == oldmid) {
7427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                break;
7437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
7442d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (escSeqStateTable_Key_2022[mid] > togo) {
7467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                hi = mid;
7477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (escSeqStateTable_Key_2022[mid] < togo) {
7487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                low = mid;
7497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else /* we found it */ {
7507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                key[0] = togo;
7517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                offset[0] = mid;
7527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return escSeqStateTable_Value_2022[mid];
7537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
7547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            oldmid = mid;
7557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return INVALID_2022;
7577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7582d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
7607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * To Unicode Callback helper function
7617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
7627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private static CoderResult toUnicodeCallback(CharsetDecoderICU cnv, int sourceChar, int targetUniChar) {
7637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CoderResult err = CoderResult.UNDERFLOW;
7647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (sourceChar > 0xff) {
7657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.toUBytesArray[0] = (byte)(sourceChar>>8);
7667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.toUBytesArray[1] = (byte)sourceChar;
7677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.toULength = 2;
7687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
7697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.toUBytesArray[0] = (byte)sourceChar;
7707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.toULength = 1;
7717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7722d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (targetUniChar == (UConverterConstants.missingCharMarker-1/* 0xfffe */)) {
7747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            err = CoderResult.unmappableForLength(1);
7757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        } else {
7767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            err = CoderResult.malformedForLength(1);
7777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        return err;
7807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
7812d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /****************************ISO-2022-JP************************************/
7837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private class CharsetDecoderISO2022JP extends CharsetDecoderICU {
7847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public CharsetDecoderISO2022JP(CharsetICU cs) {
7857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(cs);
7867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
7882d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
7897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void implReset() {
7907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.implReset();
7917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.reset();
7927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
7932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        /*
7942d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert         * Map 00..7F to Unicode according to JIS X 0201.
7957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * */
7967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int jisx201ToU(int value) {
7977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (value < 0x5c) {
7987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return value;
7997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (value == 0x5c) {
8007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return 0xa5;
8017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (value == 0x7e) {
8027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return 0x203e;
8037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else { /* value <= 0x7f */
8047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return value;
8057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
8087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Convert a pair of JIS X 208 21..7E bytes to Shift-JIS.
8097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * If either byte is outside 21..7E make sure that the result is not valid
8107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * for Shift-JIS so that the converter catches it.
8117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Some invalid byte values already turn into equally invalid Shift-JIS
8127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * byte values and need not be tested explicitly.
8137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
8147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private void _2022ToSJIS(char c1, char c2, byte []bytes) {
8157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if ((c1&1) > 0) {
8167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                ++c1;
8177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (c2 <= 0x5f) {
8187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    c2 += 0x1f;
8197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if (c2 <= 0x7e) {
8207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    c2 += 0x20;
8217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
8227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    c2 = 0; /* invalid */
8237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
8247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
8257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if ((c2 >= 0x21) && (c2 <= 0x7e)) {
8267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    c2 += 0x7e;
8277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
8287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    c2 = 0; /* invalid */
8297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
8307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8312d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            c1 >>=1;
8337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (c1 <= 0x2f) {
8347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c1 += 0x70;
8357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (c1 <= 0x3f) {
8367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c1 += 0xb0;
8377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else {
8387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                c1 = 0; /* invalid */
8397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            bytes[0] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & c1);
8417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            bytes[1] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & c2);
8427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
8437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
8442d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
8457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @SuppressWarnings("fallthrough")
8467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult decodeLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets, boolean flush) {
8477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoGetTrail = false;
8487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoEscape = false;
8497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
8507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte []tempBuf = new byte[2];
8517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int targetUniChar = 0x0000;
8527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mySourceChar = 0x0000;
8537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mySourceCharTemp = 0x0000; // use for getTrail label call.
8547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte cs; /* StateEnum */
8557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte csTemp= 0; // use for getTrail label call.
8562d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.key != 0) {
8587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial escape sequence */
8597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // goto escape;
8607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoEscape = true;
8617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (toULength == 1 && source.hasRemaining() && target.hasRemaining()) {
8627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial double-byte character */
8637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                mySourceChar = (toUBytesArray[0] & UConverterConstants.UNSIGNED_BYTE_MASK);
8647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                toULength = 0;
8657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                cs = myConverterData.toU2022State.cs[myConverterData.toU2022State.g];
8667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // goto getTrailByte;
8677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                mySourceCharTemp = 0x99;
8687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoGetTrail = true;
8697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
8702d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (source.hasRemaining() || gotoEscape || gotoGetTrail) {
8727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // This code is here for the goto escape label call above.
8737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (gotoEscape) {
8747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    mySourceCharTemp = ESC_2022;
8757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
8762d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                targetUniChar = UConverterConstants.missingCharMarker;
8782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (gotoEscape || gotoGetTrail || target.hasRemaining()) {
8807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!gotoEscape && !gotoGetTrail) {
8817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceChar = source.get() & UConverterConstants.UNSIGNED_BYTE_MASK;
8827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceCharTemp = mySourceChar;
8837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
8842d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    switch (mySourceCharTemp) {
8867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case UConverterConstants.SI:
8877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.version == 3) {
8887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.g = 0;
8897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
8907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
8917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* only JIS7 uses SI/SO, not ISO-2022-JP-x */
8927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false;
8937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
8947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
8952d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
8967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case UConverterConstants.SO:
8977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.version == 3) {
8987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* JIS7: switch to G1 half-width Katakana */
8997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.cs[1] = HWKANA_7BIT;
9007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.g = 1;
9012d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                            continue;
9027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
9037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* only JIS7 uses SI/SO, not ISO-2022-JP-x */
9047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false; /* reset this, we have a different error */
9057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
9067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
9087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case ESC_2022:
9097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!gotoEscape) {
9107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            source.position(source.position() - 1);
9117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
9127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            gotoEscape = false;
9137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// escape:
9157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        {
9167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int mySourceBefore = source.position();
9177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int toULengthBefore = this.toULength;
9182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
9197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = changeState_2022(this, source, variant);
9207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* If in ISO-2022-JP only and we successully completed an escape sequence, but previous segment was empty, create an error */
9227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if(myConverterData.version == 0 && myConverterData.key == 0 && !err.isError() && myConverterData.isEmptySegment) {
9237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                err = CoderResult.malformedForLength(source.position() - mySourceBefore);
9247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                this.toULength = toULengthBefore + (source.position() - mySourceBefore);
9257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
9267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* invalid or illegal escape sequence */
9297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if(err.isError()){
9307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false; /* Reset to avoid future spurious errors */
9317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return err;
9327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* If we successfully completed an escape sequence, we begin a new segment, empty so far */
9347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if(myConverterData.key == 0) {
9357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = true;
9367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
9387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
9397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* ISO-2022-JP does not use single-byte (C1) SS2 and SS3 */
9407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case CR:
9417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* falls through */
9427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case LF:
9437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* automatically reset to single-byte mode */
9447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.toU2022State.cs[0] != ASCII && myConverterData.toU2022State.cs[0] != JISX201) {
9457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.cs[0] = ASCII;
9467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.cs[2] = 0;
9487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 0;
9497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* falls through */
9507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    default :
9517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* convert one or two bytes */
9527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.isEmptySegment = false;
9537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        cs = myConverterData.toU2022State.cs[myConverterData.toU2022State.g];
9547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        csTemp = cs;
9557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (gotoGetTrail) {
9567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            csTemp = (byte)0x99;
9577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
9587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!gotoGetTrail && ((mySourceChar >= 0xa1) && (mySourceChar <= 0xdf) && myConverterData.version == 4 && !IS_JP_DBCS(cs))) {
9597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* 8-bit halfwidth katakana in any single-byte mode for JIS8 */
9607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            targetUniChar = mySourceChar + (HWKANA_START - 0xa1);
9612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
9627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* return from a single-shift state to the previous one */
9637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (myConverterData.toU2022State.g >= 2) {
9647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                myConverterData.toU2022State.g = myConverterData.toU2022State.prevG;
9657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
9667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
9677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            switch(csTemp) {
9687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            case ASCII:
9697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (mySourceChar <= 0x7f) {
9707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetUniChar = mySourceChar;
9717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
9727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
9737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            case ISO8859_1:
9747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (mySourceChar <= 0x7f) {
9757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetUniChar = mySourceChar + 0x80;
9767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
9777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* return from a single-shift state to the prevous one */
9787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                myConverterData.toU2022State.g = myConverterData.toU2022State.prevG;
9797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
9807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            case ISO8859_7:
9817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (mySourceChar <= 0x7f) {
9827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* convert mySourceChar+0x80 to use a normal 8-bit table */
9837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetUniChar = CharsetMBCS.MBCS_SINGLE_SIMPLE_GET_NEXT_BMP(myConverterData.myConverterArray[cs].mbcs,
9847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            mySourceChar+0x80);
9857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
9867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* return from a single-shift state to the previous one */
9877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                myConverterData.toU2022State.g = myConverterData.toU2022State.prevG;
9887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
9897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            case JISX201:
9907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (mySourceChar <= 0x7f) {
9917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetUniChar = jisx201ToU(mySourceChar);
9927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
9937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
9947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            case HWKANA_7BIT:
9957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if ((mySourceChar >= 0x21) && (mySourceChar <= 0x5f)) {
9967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* 7-bit halfwidth Katakana */
9977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetUniChar = mySourceChar + (HWKANA_START - 0x21);
9987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
9997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
10007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            default :
10017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* G0 DBCS */
10027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (gotoGetTrail || source.hasRemaining()) {
10037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// getTrailByte:
10047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    int tmpSourceChar;
10057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    gotoGetTrail = false;
10067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    short trailByte;
10077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    boolean leadIsOk, trailIsOk;
10082d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
10097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    trailByte = (short)(source.get(source.position()) & UConverterConstants.UNSIGNED_BYTE_MASK);
10107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /*
10117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * Ticket 5691: consistent illegal sequences:
10127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * - We include at least the first byte in the illegal sequence.
10137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * - If any of the non-initial bytes could be the start of a character,
10147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     *   we stop the illegal sequence before the first one of those.
10152d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                                     *
10167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * In ISO-2022 DBCS, if the second byte is in the 21..7e range or is
10177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * an ESC/SO/SI, we report only the first byte as the illegal sequence.
10187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * Otherwise we convert or report the pair of bytes.
10197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     */
10207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    leadIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (mySourceChar - 0x21)) <= (0x7e - 0x21);
10217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    trailIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (trailByte - 0x21)) <= (0x7e - 0x21);
10227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (leadIsOk && trailIsOk) {
10237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        source.get();
10247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tmpSourceChar = (mySourceChar << 8) | trailByte;
10257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        if (cs == JISX208) {
10267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            _2022ToSJIS((char)mySourceChar, (char)trailByte, tempBuf);
10277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            mySourceChar = tmpSourceChar;
10287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        } else {
10297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            /* Copy before we modify tmpSourceChar so toUnicodeCallback() sees the correct bytes. */
10307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            mySourceChar = tmpSourceChar;
10317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            if (cs == KSC5601) {
10327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                                tmpSourceChar += 0x8080; /* = _2022ToGR94DBCS(tmpSourceChar) */
10337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            }
10347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            tempBuf[0] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & (tmpSourceChar >> 8));
10357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            tempBuf[1] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & tmpSourceChar);
10367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        }
10377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        targetUniChar = MBCSSimpleGetNextUChar(myConverterData.myConverterArray[cs], ByteBuffer.wrap(tempBuf), false);
10387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) {
10397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        /* report a pair of illegal bytes if the second byte is not a DBCS starter */
10407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        source.get();
10417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        /* add another bit so that the code below writes 2 bytes in case of error */
10427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        mySourceChar = 0x10000 | (mySourceChar << 8) | trailByte;
10437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
10447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
10457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    toUBytesArray[0] = (byte)mySourceChar;
10467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    toULength = 1;
10477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    // goto endloop
10487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    return err;
10497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
10507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } /* end of inner switch */
10517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
10527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
10537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } /* end of outer switch */
10542d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
10557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (targetUniChar < (UConverterConstants.missingCharMarker-1/*0xfffe*/)) {
10567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
10577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(target.remaining(), source.remaining() - (mySourceChar <= 0xff ? 1 : 2));
10587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
10597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put((char)targetUniChar);
10607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (targetUniChar > UConverterConstants.missingCharMarker) {
10617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* disassemble the surrogate pair and write to output */
10627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        targetUniChar -= 0x0010000;
10637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put((char)(0xd800 + (char)(targetUniChar>>10)));
10647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.position(target.position()-1);
10657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
10667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(target.remaining(), source.remaining() - (mySourceChar <= 0xff ? 1 : 2));
10677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
10687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.get();
10697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (target.hasRemaining()) {
10707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            target.put((char)(0xdc00+(char)(targetUniChar&0x3ff)));
10717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            target.position(target.position()-1);
10727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (offsets != null) {
10737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                offsets.put(target.remaining(), source.remaining() - (mySourceChar <= 0xff ? 1 : 2));
10747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
10757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            target.get();
10767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
10772d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                            charErrorBufferArray[charErrorBufferLength++] =
10787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                (char)(0xdc00+(char)(targetUniChar&0x3ff));
10797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
10807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
10817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* Call the callback function */
10827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = toUnicodeCallback(this, mySourceChar, targetUniChar);
10837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
10847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
10857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else { /* goes with "if (target.hasRemaining())" way up near the top of the function */
10867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.OVERFLOW;
10877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
10887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
10897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
10907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert//endloop:
10917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
10927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
10937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    } // end of class CharsetDecoderISO2022JP
10942d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
10957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /****************************ISO-2022-CN************************************/
10967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private class CharsetDecoderISO2022CN extends CharsetDecoderICU {
10977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public CharsetDecoderISO2022CN(CharsetICU cs) {
10987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(cs);
10997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11012d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
11027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void implReset() {
11037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.implReset();
11047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.reset();
11057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
11067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
11087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        @SuppressWarnings("fallthrough")
11097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult decodeLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets, boolean flush) {
11107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
11117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] tempBuf = new byte[3];
11127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int targetUniChar = 0x0000;
11137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mySourceChar = 0x0000;
11147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mySourceCharTemp = 0x0000;
11157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoEscape = false;
11167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoGetTrailByte = false;
11172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.key != 0) {
11197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial escape sequence */
11207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // goto escape;
11217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoEscape = true;
11227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (toULength == 1 && source.hasRemaining() && target.hasRemaining()) {
11237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial double-byte character */
11247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                mySourceChar = (toUBytesArray[0] & UConverterConstants.UNSIGNED_BYTE_MASK);
11257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                toULength = 0;
11267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                targetUniChar = UConverterConstants.missingCharMarker;
11277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // goto getTrailByte
11287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoGetTrailByte = true;
11297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
11302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (source.hasRemaining() || gotoGetTrailByte || gotoEscape) {
11327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                targetUniChar = UConverterConstants.missingCharMarker;
11332d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (target.hasRemaining() || gotoEscape) {
11357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (gotoEscape) {
11367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceChar = ESC_2022; // goto escape label
11377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceCharTemp = mySourceChar;
11387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (gotoGetTrailByte) {
11397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceCharTemp = 0xff; // goto getTrailByte; set mySourceCharTemp to go to default
11407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
11417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceChar = UConverterConstants.UNSIGNED_BYTE_MASK & source.get();
11427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceCharTemp = mySourceChar;
11437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
11442d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    switch (mySourceCharTemp) {
11467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case UConverterConstants.SI:
11477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 0;
11487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.isEmptySegment) {
11497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false; /* we are handling it, reset to avoid future spurious errors */
11507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.malformedForLength(1);
11517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            this.toUBytesArray[0] = (byte)mySourceChar;
11527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            this.toULength = 1;
11537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return err;
11547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
11557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
11562d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case UConverterConstants.SO:
11587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.toU2022State.cs[1] != 0) {
11597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.toU2022State.g = 1;
11607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = true;  /* Begin a new segment, empty so far */
11617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            continue;
11627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
11637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* illegal to have SO before a matching designator */
11647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false; /* Handling a different error, reset this to avoid future spurious errs */
11657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
11667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
11672d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case ESC_2022:
11697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!gotoEscape) {
11707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            source.position(source.position()-1);
11717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
11727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// escape label
11737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        gotoEscape = false;
11747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        {
11757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int mySourceBefore = source.position();
11767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int toULengthBefore = this.toULength;
11777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = changeState_2022(this, source, ISO_2022_CN);
11797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* After SO there must be at least one character before a designator (designator error handled separately) */
11817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if(myConverterData.key == 0 && !err.isError() && myConverterData.isEmptySegment) {
11827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                err = CoderResult.malformedForLength(source.position() - mySourceBefore);
11837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                this.toULength = toULengthBefore + (source.position() - mySourceBefore);
11847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
11857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
11867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
11877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* invalid or illegal escape sequence */
11887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if(err.isError()){
11897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false; /* Reset to avoid future spurious errors */
11907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return err;
11917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
11927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
11932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
11947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /*ISO-2022-CN does not use single-byte (C1) SS2 and SS3 */
11957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case CR:
11967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* falls through */
11977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    case LF:
11987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.reset();
11997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* falls through */
12007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    default:
12017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* converter one or two bytes */
12027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.isEmptySegment = false;
12037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.toU2022State.g != 0 || gotoGetTrailByte) {
12047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (source.hasRemaining() || gotoGetTrailByte) {
12057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                UConverterSharedData cnv;
12067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                byte tempState;
12077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                int tempBufLen;
12087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                boolean leadIsOk, trailIsOk;
12097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                short trailByte;
12107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// getTrailByte: label
12117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                gotoGetTrailByte = false; // reset gotoGetTrailByte
12122d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
12137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                trailByte = (short)(source.get(source.position()) & UConverterConstants.UNSIGNED_BYTE_MASK);
12147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /*
12157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 * Ticket 5691: consistent illegal sequences:
12167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 * - We include at least the first byte in the illegal sequence.
12177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 * - If any of the non-initial bytes could be the start of a character,
12187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 *   we stop the illegal sequence before the first one of those.
12192d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                                 *
12207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 * In ISO-2022 DBCS, if the second byte is in the range 21..7e range or is
12217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 * an ESC/SO/SI, we report only the first byte as the illegal sequence.
12227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 * Otherwise we convert or report the pair of bytes.
12237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                 */
12247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                leadIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (mySourceChar - 0x21)) <= (0x7e - 0x21);
12257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                trailIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (trailByte - 0x21)) <= (0x7e - 0x21);
12267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (leadIsOk && trailIsOk) {
12277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    source.get();
12287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    tempState = myConverterData.toU2022State.cs[myConverterData.toU2022State.g];
12297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (tempState > CNS_11643_0) {
12307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        cnv = myConverterData.myConverterArray[CNS_11643];
12317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBuf[0] = (byte)(0x80 + (tempState - CNS_11643_0));
12327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBuf[1] = (byte)mySourceChar;
12337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBuf[2] = (byte)trailByte;
12347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBufLen = 3;
12357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    } else {
12367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        cnv = myConverterData.myConverterArray[tempState];
12377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBuf[0] = (byte)mySourceChar;
12387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBuf[1] = (byte)trailByte;
12397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        tempBufLen = 2;
12407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
12417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    ByteBuffer tempBuffer = ByteBuffer.wrap(tempBuf);
12427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    tempBuffer.limit(tempBufLen);
12437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetUniChar = MBCSSimpleGetNextUChar(cnv, tempBuffer, false);
12447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    mySourceChar = (mySourceChar << 8) | trailByte;
12452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
12467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) {
12477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* report a pair of illegal bytes if the second byte is not a DBCS starter */
12487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    source.get();
12497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* add another bit so that the code below writes 2 bytes in case of error */
12507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    mySourceChar = 0x10000 | (mySourceChar << 8) | trailByte;
12517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
12527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (myConverterData.toU2022State.g >= 2) {
12537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* return from a single-shift state to the previous one */
12547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.toU2022State.g = myConverterData.toU2022State.prevG;
12557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
12567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
12577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                toUBytesArray[0] = (byte)mySourceChar;
12587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                toULength = 1;
12597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // goto endloop;
12607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                return err;
12617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
12627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
12637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (mySourceChar <= 0x7f) {
12647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetUniChar = (char)mySourceChar;
12657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
12667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
12677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
12687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
12697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if ((UConverterConstants.UNSIGNED_INT_MASK&targetUniChar) < (UConverterConstants.UNSIGNED_INT_MASK&(UConverterConstants.missingCharMarker-1))) {
12707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
12717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.array()[target.position()] = source.remaining() - (mySourceChar <= 0xff ? 1 : 2);
12727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
12737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put((char)targetUniChar);
12747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if ((UConverterConstants.UNSIGNED_INT_MASK&targetUniChar) > (UConverterConstants.UNSIGNED_INT_MASK&(UConverterConstants.missingCharMarker))) {
12757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* disassemble the surrogate pair and write to output */
12767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        targetUniChar -= 0x0010000;
12777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put((char)(0xd800+(char)(targetUniChar>>10)));
12787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
12797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.array()[target.position()-1] = source.position() - (mySourceChar <= 0xff ? 1 : 2);
12807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
12817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (target.hasRemaining()) {
12827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            target.put((char)(0xdc00+(char)(targetUniChar&0x3ff)));
12837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (offsets != null) {
12847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                offsets.array()[target.position()-1] = source.position() - (mySourceChar <= 0xff ? 1 : 2);
12857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
12867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
12877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            charErrorBufferArray[charErrorBufferLength++] = (char)(0xdc00+(char)(targetUniChar&0x3ff));
12887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
12897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
12902d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                        /* Call the callback function */
12917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = toUnicodeCallback(this, mySourceChar, targetUniChar);
12927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
12937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
12942d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
12957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
12967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.OVERFLOW;
12977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
12987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
12997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
13002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
13027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
13057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /************************ ISO-2022-KR ********************/
13067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private class CharsetDecoderISO2022KR extends CharsetDecoderICU {
13077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public CharsetDecoderISO2022KR(CharsetICU cs) {
13087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(cs);
13097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13112d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
13127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void implReset() {
13137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.implReset();
13147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInitialStateToUnicodeKR();
13157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.reset();
13167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
13172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
13197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult decodeLoop(ByteBuffer source, CharBuffer target, IntBuffer offsets, boolean flush) {
13207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
13217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int mySourceChar = 0x0000;
13227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int targetUniChar = 0x0000;
13237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] tempBuf = new byte[2];
13247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean usingFallback;
13257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoGetTrailByte = false;
13267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoEscape = false;
13272d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.version == 1) {
13297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return decodeLoopIBM(myConverterData.currentDecoder, source, target, offsets, flush);
13307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
13312d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* initialize state */
13337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            usingFallback = isFallbackUsed();
13342d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.key != 0) {
13367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial escape sequence */
13377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoEscape = true;
13387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (toULength == 1 && source.hasRemaining() && target.hasRemaining()) {
13397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial double-byte character */
13407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                mySourceChar = (toUBytesArray[0] & UConverterConstants.UNSIGNED_BYTE_MASK);
13417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                toULength = 0;
13427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoGetTrailByte = true;
13437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
13442d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (source.hasRemaining() || gotoGetTrailByte || gotoEscape) {
13467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (target.hasRemaining() || gotoGetTrailByte || gotoEscape) {
13477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!gotoGetTrailByte && !gotoEscape) {
13487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        mySourceChar = (char)(source.get() & UConverterConstants.UNSIGNED_BYTE_MASK);
13497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
13502d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!gotoGetTrailByte && !gotoEscape && mySourceChar == UConverterConstants.SI) {
13527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 0;
13537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.isEmptySegment) {
13547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.isEmptySegment = false; /* we are handling it, reset to avoid future spurious errors */
13557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.malformedForLength(1);
13567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            this.toUBytesArray[0] = (byte)mySourceChar;
13577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            this.toULength = 1;
13587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return err;
13597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
13607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* consume the source */
13617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
13627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (!gotoGetTrailByte && !gotoEscape && mySourceChar == UConverterConstants.SO) {
13637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.toU2022State.g = 1;
13647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.isEmptySegment = true;
13657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* consume the source */
13667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
13677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (!gotoGetTrailByte && (gotoEscape || mySourceChar == ESC_2022)) {
13687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (!gotoEscape) {
13697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            source.position(source.position()-1);
13707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
13717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// escape label
13727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        gotoEscape = false; // reset gotoEscape flag
13732d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                        myConverterData.isEmptySegment = false; /* Any invalid ESC sequences will be detected separately, so just reset this */
13747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = changeState_2022(this, source, ISO_2022_KR);
13757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (err.isError()) {
13767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            return err;
13777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
13787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        continue;
13797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
13807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.isEmptySegment = false; /* Any invalid char errors will be detected separately, so just reset this */
13817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.toU2022State.g == 1 || gotoGetTrailByte) {
13827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (source.hasRemaining() || gotoGetTrailByte) {
13837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            boolean leadIsOk, trailIsOk;
13847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            short trailByte;
13857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// getTrailByte label
13867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            gotoGetTrailByte = false; // reset gotoGetTrailByte flag
13872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
13887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            trailByte = (short)(source.get(source.position()) & UConverterConstants.UNSIGNED_BYTE_MASK);
13897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            targetUniChar = UConverterConstants.missingCharMarker;
13907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /*
13917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * Ticket 5691: consistent illegal sequences:
13927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * - We include at least the first byte in the illegal sequence.
13937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * - If any of the non-initial bytes could be the start of a character,
13947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             *   we stop the illegal sequence before the first one of those.
13952d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                             *
13967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * In ISO-2022 DBCS, if the second byte is in the 21..7e range or is
13977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * an ESC/SO/SI, we report only the first byte as the illegal sequence.
13987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * Otherwise we convert or report the pair of bytes.
13997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             */
14007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            leadIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (mySourceChar - 0x21)) <= (0x7e - 0x21);
14017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            trailIsOk = (short)(UConverterConstants.UNSIGNED_BYTE_MASK & (trailByte - 0x21)) <= (0x7e - 0x21);
14027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (leadIsOk && trailIsOk) {
14037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                source.get();
14047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                tempBuf[0] = (byte)(mySourceChar + 0x80);
14057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                tempBuf[1] = (byte)(trailByte + 0x80);
14067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetUniChar = MBCSSimpleGetNextUChar(myConverterData.currentConverter.sharedData, ByteBuffer.wrap(tempBuf), usingFallback);
14077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                mySourceChar = (char)((mySourceChar << 8) | trailByte);
14087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else if (!(trailIsOk || IS_2022_CONTROL(trailByte))) {
14097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* report a pair of illegal bytes if the second byte is not a DBCS starter */
14107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                source.get();
14117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* add another bit so that the code below writes 2 bytes in case of error */
14127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                mySourceChar = (char)(0x10000 | (mySourceChar << 8) | trailByte);
14137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
14147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
14157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            toUBytesArray[0] = (byte)mySourceChar;
14167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            toULength = 1;
14177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
14187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
14197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (mySourceChar <= 0x7f) {
14207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int savedSourceLimit = source.limit();
14217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int savedSourcePosition = source.position();
14227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        source.limit(source.position());
14232d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                        source.position(source.position()-1);
14247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        targetUniChar = MBCSSimpleGetNextUChar(myConverterData.currentConverter.sharedData, source, usingFallback);
14257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        source.limit(savedSourceLimit);
14267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        source.position(savedSourcePosition);
14277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
14287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        targetUniChar = 0xffff;
14297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
14307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (targetUniChar < 0xfffe) {
14317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put((char)targetUniChar);
14327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
14337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.array()[target.position()] = source.position() - (mySourceChar <= 0xff ? 1 : 2);
14347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
14357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
14367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* Call the callback function */
14377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = toUnicodeCallback(this, mySourceChar, targetUniChar);
14387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
14397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
14407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
14417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.OVERFLOW;
14427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
14437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
14447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
14452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
14467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
14477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
14482d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
14497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult decodeLoopIBM(CharsetDecoderMBCS cnv, ByteBuffer source, CharBuffer target, IntBuffer offsets, boolean flush) {
14507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
14517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int sourceStart;
14527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int sourceLimit;
14537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int argSource;
14547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int argTarget;
14557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoEscape = false;
14567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int oldSourceLimit;
14572d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
14587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* remember the original start of the input for offsets */
14597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            sourceStart = argSource = source.position();
14602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
14617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.key != 0) {
14627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* continue with a partial escape sequence */
14637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoEscape = true;
14647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
14652d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
14667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (gotoEscape || (!err.isError() && source.hasRemaining())) {
14677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (!gotoEscape) {
14687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* Find the end of the buffer e.g : Next Escape Seq | end of Buffer */
14697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    int oldSourcePos = source.position();
14707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sourceLimit = getEndOfBuffer_2022(source);
14717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    source.position(oldSourcePos);
14727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (source.position() != sourceLimit) {
14737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /*
14747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * get the current partial byte sequence
14752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                         *
14767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * it needs to be moved between the public and the subconverter
14777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * so that the conversion frameword, which only sees the public
14787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * converter, can handle truncated and illegal input etc.
14797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
14807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (toULength > 0) {
14817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            cnv.toUBytesArray = toUBytesArray.clone();
14827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
14837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        cnv.toULength = toULength;
14842d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
14857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /*
14867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * Convert up to the end of the input, or to before the next escape character.
14877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * Does not handle conversion extensions because the preToU[] state etc.
14887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * is not copied.
14897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
14907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        argTarget = target.position();
14917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        oldSourceLimit = source.limit(); // save the old source limit change to new one
14927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        source.limit(sourceLimit);
14937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = myConverterData.currentDecoder.cnvMBCSToUnicodeWithOffsets(source, target, offsets, flush);
14947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        source.limit(oldSourceLimit); // restore source limit;
14957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null && sourceStart != argSource) {
14967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* update offsets to base them on the actual start of the input */
14977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int delta = argSource - sourceStart;
14987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            while (argTarget < target.position()) {
14997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                int currentOffset = offsets.get();
15007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                offsets.position(offsets.position()-1);
15017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (currentOffset >= 0) {
15027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    offsets.put(currentOffset + delta);
15037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    offsets.position(offsets.position()-1);
15047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
15057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                offsets.get();
15067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                target.get();
15077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
15087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
15097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        argSource = source.position();
15102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
15117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* copy input/error/overflow buffers */
15127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (cnv.toULength > 0) {
15137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            toUBytesArray = cnv.toUBytesArray.clone();
15147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
15157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        toULength = cnv.toULength;
15162d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
15177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (err.isOverflow()) {
15187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (cnv.charErrorBufferLength > 0) {
15197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                charErrorBufferArray = cnv.charErrorBufferArray.clone();
15207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
15217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            charErrorBufferLength = cnv.charErrorBufferLength;
15227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            cnv.charErrorBufferLength = 0;
15237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
15247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
15252d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
15267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (err.isError() || err.isOverflow() || (source.position() == source.limit())) {
15277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        return err;
15287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
15297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
15307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// escape label
15317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoEscape = false;
15327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = changeState_2022(this, source, ISO_2022_KR);
15337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
15347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
15357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
15367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
15372d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
15387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /******************** from unicode **********************/
15397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* preference order of JP charsets */
15407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte []jpCharsetPref = {
15417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ASCII,
15427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        JISX201,
15437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ISO8859_1,
15447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        JISX208,
1545bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert        ISO8859_7,
15467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        JISX212,
15477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        GB2312,
15487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        KSC5601,
15497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        HWKANA_7BIT
15507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
15517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
15527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * The escape sequences must be in order of the enum constants like JISX201 = 3,
15537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * not in order of jpCharsetPref[]!
15547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
15557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte [][]escSeqChars = {
15567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x28, 0x42},        /* <ESC>(B  ASCII       */
15577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x2E, 0x41},        /* <ESC>.A  ISO-8859-1  */
15587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x2E, 0x46},        /* <ESC>.F  ISO-8859-7  */
15597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x28, 0x4A},        /* <ESC>(J  JISX-201    */
15607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x24, 0x42},        /* <ESC>$B  JISX-208    */
15617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x24, 0x28, 0x44},  /* <ESC>$(D JISX-212    */
15627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x24, 0x41},        /* <ESC>$A  GB2312      */
15637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x24, 0x28, 0x43},  /* <ESC>$(C KSC5601     */
15647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            { 0x1B, 0x28, 0x49}         /* <ESC>(I  HWKANA_7BIT */
15657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
15667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
15677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * JIS X 0208 has fallbacks from Unicode half-width Katakana to full-width (DBCS)
15687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Katakana.
15697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Now that we use a Shift-JIS table for JIS X 0208 we need to hardcode these fallbacks
15707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * because Shift-JIS roundtrips half-width Katakana to single bytes.
15717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * These were the only fallbacks in ICU's jisx-208.ucm file.
15727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
15737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static char []hwkana_fb = {
15747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2123,  /* U+FF61 */
15757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2156,
15767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2157,
15777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2122,
15787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2126,
15797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2572,
15807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2521,
15817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2523,
15827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2525,
15837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2527,
15847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2529,
15857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2563,
15867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2565,
15877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2567,
15887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2543,
15897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x213C,  /* U+FF70 */
15907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2522,
15917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2524,
15927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2526,
15937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2528,
15947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x252A,
15957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x252B,
15967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x252D,
15977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x252F,
15987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2531,
15997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2533,
16007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2535,
16017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2537,
16027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2539,
16037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x253B,
16047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x253D,
16057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x253F,  /* U+FF80 */
16067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2541,
16077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2544,
16087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2546,
16097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2548,
16107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x254A,
16117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x254B,
16127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x254C,
16137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x254D,
16147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x254E,
16157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x254F,
16167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2552,
16177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2555,
16187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2558,
16197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x255B,
16207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x255E,
16217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x255F,  /* U+FF90 */
16227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2560,
16237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2561,
16247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2562,
16257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2564,
16267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2566,
16277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2568,
16287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2569,
16297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x256A,
16307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x256B,
16317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x256C,
16327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x256D,
16337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x256F,
16347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x2573,
16357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x212B,
16367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        0x212C   /* U+FF9F */
16377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
16382d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    protected byte [][]fromUSubstitutionChar = new byte[][]{ { (byte)0x1A }, { (byte)0x2F, (byte)0x7E} };
16407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /****************************ISO-2022-JP************************************/
16417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private class CharsetEncoderISO2022JP extends CharsetEncoderICU {
16427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public CharsetEncoderISO2022JP(CharsetICU cs) {
16437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(cs, fromUSubstitutionChar[0]);
16447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
16452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16462d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
16477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void implReset() {
16487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.implReset();
16497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.reset();
16507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
16517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* Map Unicode to 00..7F according to JIS X 0201. Return U+FFFE if unmappable. */
16527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int jisx201FromU(int value) {
16537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (value <= 0x7f) {
16547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (value != 0x5c && value != 0x7e) {
16557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    return value;
16567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
16577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (value == 0xa5) {
16587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return 0x5c;
16597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else if (value == 0x203e) {
16607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return 0x7e;
16617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
16627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return (int)(UConverterConstants.UNSIGNED_INT_MASK & 0xfffe);
16637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
16642d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
16667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Take a valid Shift-JIS byte pair, check that it is in the range corresponding
16677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * to JIS X 0208, and convert it to a pair of 21..7E bytes.
16687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Return 0 if the byte pair is out of range.
16697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
16707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private int _2022FromSJIS(int value) {
16717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            short trail;
16722d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (value > 0xEFFC) {
16747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return 0; /* beyond JIS X 0208 */
16757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
16762d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            trail = (short)(value & UConverterConstants.UNSIGNED_BYTE_MASK);
16782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            value &= 0xff00; /* lead byte */
16807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (value <= 0x9f00) {
16817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                value -= 0x7000;
16827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else { /* 0xe000 <= value <= 0xef00 */
16837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                value -= 0xb000;
16847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
16852d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            value <<= 1;
16872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (trail <= 0x9e) {
16897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                value -= 0x100;
16907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (trail <= 0x7e) {
16917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    value |= ((trail - 0x1f) & UConverterConstants.UNSIGNED_BYTE_MASK);
16927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
16937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    value |= ((trail - 0x20) & UConverterConstants.UNSIGNED_BYTE_MASK);
16947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
16957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } else { /* trail <= 0xfc */
16967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                value |= ((trail - 0x7e) & UConverterConstants.UNSIGNED_BYTE_MASK);
16977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
16982d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
16997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return value;
17007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
17017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* This overrides the cbFromUWriteSub method in CharsetEncoderICU */
17022d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
17032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        CoderResult cbFromUWriteSub (CharsetEncoderICU encoder,
17047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                CharBuffer source, ByteBuffer target, IntBuffer offsets){
17057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                CoderResult err = CoderResult.UNDERFLOW;
17067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte[] buffer = new byte[8];
17077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int i = 0;
17087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte[] subchar;
17097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                subchar = encoder.replacement();
17102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte cs;
17127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (myConverterData.fromU2022State.g == 1) {
17137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* JIS7: switch from G1 to G0 */
17147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.fromU2022State.g = 0;
17157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = UConverterConstants.SI;
17167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
17177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                cs = myConverterData.fromU2022State.cs[0];
17182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (cs != ASCII && cs != JISX201) {
17207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* not in ASCII or JIS X 0201: switch to ASCII */
17217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.fromU2022State.cs[0] = ASCII;
17227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = 0x1B;
17237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = 0x28;
17247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = 0x42;
17257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
17262d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buffer[i++] = subchar[0];
17282d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = CharsetEncoderICU.fromUWriteBytes(this, buffer, 0, i, target, offsets, source.position() - 1);
17307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
17317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return err;
17327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17332d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17342d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
17357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult encodeLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
17367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
17377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int sourceChar;
17387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte cs, g;
17397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int choiceCount;
17407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int len, outLen;
17417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] choices = new byte[10];
17427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int targetValue = 0;
17437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean usingFallback;
17447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] buffer = new byte[8];
17457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean getTrail = false; // use for getTrail label
17467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int oldSourcePos; // for proper error handling
17472d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            choiceCount = 0;
17492d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* check if the last codepoint of previous buffer was a lead surrogate */
17517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if ((sourceChar = fromUChar32) != 0 && target.hasRemaining()) {
17527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                getTrail = true;
17537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
17542d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
17557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (getTrail || source.hasRemaining()) {
17567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (getTrail || target.hasRemaining()) {
17577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    oldSourcePos = source.position();
17587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!getTrail) { /* skip if going to getTrail label */
17597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        sourceChar = source.get();
17607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
17617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* check if the char is a First surrogate */
17627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (getTrail || UTF16.isSurrogate((char)sourceChar)) {
17637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (getTrail || UTF16.isLeadSurrogate((char)sourceChar)) {
17642d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert// getTrail:
17657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (getTrail) {
17667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                getTrail = false;
17677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
17687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* look ahead to find the trail surrogate */
17697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (source.hasRemaining()) {
17707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* test the following code unit */
17717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                char trail = source.get();
17727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* go back to the previous position */
17737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                source.position(source.position()-1);
17747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (UTF16.isTrailSurrogate(trail)) {
17757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    source.get();
17767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    sourceChar = UCharacter.getCodePoint((char)sourceChar, trail);
17777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    fromUChar32 = 0x00;
17787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* convert this supplementary code point */
17797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* exit this condition tree */
17807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
17817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* this is an unmatched lead code unit (1st surrogate) */
17827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* callback(illegal) */
17837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    err = CoderResult.malformedForLength(1);
17847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    fromUChar32 = sourceChar;
17857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
17867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
17877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
17887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* no more input */
17897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                fromUChar32 = sourceChar;
17907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
17917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
17927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
17937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* this is an unmatched trail code unit (2nd surrogate) */
17947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* callback(illegal) */
17957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.malformedForLength(1);
17967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            fromUChar32 = sourceChar;
17977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
17987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
17997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
18002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* do not convert SO/SI/ESC */
18027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (IS_2022_CONTROL(sourceChar)) {
18037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* callback(illegal) */
18047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.malformedForLength(1);
18057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        fromUChar32 = sourceChar;
18067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
18077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
18082d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* do the conversion */
18102d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (choiceCount == 0) {
18127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        char csm;
18137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /*
18147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * The csm variable keeps track of which charsets are allowed
18157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * and not used yet while building the choices[].
18167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
18177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        csm = (char)jpCharsetMasks[myConverterData.version];
18187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        choiceCount = 0;
18192d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* JIS7/8: try single-byte half-width Katakana before JISX208 */
18217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.version == 3 || myConverterData.version == 4) {
18227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            choices[choiceCount++] = HWKANA_7BIT;
18237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
18247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* Do not try single-bit half-width Katakana for other versions. */
18257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        csm &= ~CSM(HWKANA_7BIT);
18262d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* try the current G0 charset */
18287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        choices[choiceCount++] = cs = myConverterData.fromU2022State.cs[0];
18297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        csm &= ~CSM(cs);
18302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* try the current G2 charset */
18327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if ((cs = myConverterData.fromU2022State.cs[2]) != 0) {
18337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            choices[choiceCount++] = cs;
18347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            csm &= ~CSM(cs);
18357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
1836bd1cbb618dcaa1ac6ba7c77dece35cb79593a5d7Fredrik Roubert
18377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* try all the other charsets */
18387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        for (int i = 0; i < jpCharsetPref.length; i++) {
18397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            cs = jpCharsetPref[i];
18407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if ((CSM(cs) & csm) != 0) {
18417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choices[choiceCount++] = cs;
18427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                csm &= ~CSM(cs);
18437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
18447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
18457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
18462d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    cs = g = 0;
18482d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    /*
18497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * len==0:  no mapping found yet
18507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * len<0:   found a fallback result:  continue looking for a roundtrip but no further fallbacks
18517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * len>0:   found a roundtrip result, done
18527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     */
18537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    len = 0;
18547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /*
18557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * We will turn off usingFallBack after finding a fallback,
18567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * but we still get fallbacks from PUA code points as usual.
18577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * Therefore, we will also need to check that we don't overwrite
18587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * an early fallback with a later one.
18597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     */
18607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    usingFallback = useFallback;
18612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for (int i = 0; i < choiceCount && len <= 0; i++) {
18637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int[] value = new int[1];
18647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int len2;
18657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        byte cs0 = choices[i];
18667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        switch (cs0) {
18677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        case ASCII:
18687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (sourceChar <= 0x7f) {
18697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetValue = sourceChar;
18707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = 1;
18717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                cs = cs0;
18727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                g = 0;
18737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
18747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
18757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        case ISO8859_1:
18767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (GR96_START <= sourceChar && sourceChar <= GR96_END) {
18777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetValue = sourceChar - 0x80;
18787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = 1;
18797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                cs = cs0;
18807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                g = 2;
18817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
18827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
18837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        case HWKANA_7BIT:
18847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (sourceChar <= HWKANA_END && sourceChar >= HWKANA_START) {
18857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (myConverterData.version == 3) {
18867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* JIS7: use G1 (SO) */
18877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* Shift U+FF61..U+FF9F to bytes 21..5F. */
18887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetValue = (int)(UConverterConstants.UNSIGNED_INT_MASK & (sourceChar - (HWKANA_START - 0x21)));
18897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    len = 1;
18907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.fromU2022State.cs[1] = cs = cs0; /* do not output an escape sequence */
18917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    g = 1;
18927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else if (myConverterData.version == 4) {
18937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* JIS8: use 8-bit bytes with any single-byte charset, see escape sequence output below */
18947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* Shift U+FF61..U+FF9F to bytes A1..DF. */
18957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetValue = (int)(UConverterConstants.UNSIGNED_INT_MASK & (sourceChar - (HWKANA_START - 0xa1)));
18967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    len = 1;
18972d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
18987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    cs = myConverterData.fromU2022State.cs[0];
18997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (IS_JP_DBCS(cs)) {
19007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        /* switch from a DBCS charset to JISX201 */
19017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        cs = JISX201;
19027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
19037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* else stay in the current G0 charset */
19047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    g = 0;
19057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
19067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* else do not use HWKANA_7BIT with other versions */
19077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
19087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
19097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        case JISX201:
19107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* G0 SBCS */
19117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            value[0] = jisx201FromU(sourceChar);
19127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (value[0] <= 0x7f) {
19137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetValue = value[0];
19147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = 1;
19157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                cs = cs0;
19167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                g = 0;
19177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                usingFallback = false;
19187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
19197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
19207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        case JISX208:
19217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* G0 DBCS from JIS table */
19227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.currentConverter.sharedData = myConverterData.myConverterArray[cs0];
19237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.currentConverter.sharedData.mbcs.outputType = CharsetMBCS.MBCS_OUTPUT_2;
19247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len2 = myConverterData.currentEncoder.fromUChar32(sourceChar, value, usingFallback);
19257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            //len2 = MBCSFromUChar32_ISO2022(myConverterData.myConverterArray[cs0], sourceChar, value, usingFallback, CharsetMBCS.MBCS_OUTPUT_2);
19267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (len2 == 2 || (len2 == -2 && len == 0)) { /* only accept DBCS: abs(len) == 2 */
19277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                value[0] = _2022FromSJIS(value[0]);
19287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (value[0] != 0) {
19297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    targetValue = value[0];
19307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    len = len2;
19317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    cs = cs0;
19327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    g = 0;
19337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    usingFallback = false;
19347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
19357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else if (len == 0 && usingFallback  && sourceChar <= HWKANA_END && sourceChar >= HWKANA_START) {
19367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetValue = hwkana_fb[sourceChar - HWKANA_START];
19377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = -2;
19387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                cs = cs0;
19397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                g = 0;
19407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                usingFallback = false;
19417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
19427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
19437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        case ISO8859_7:
19447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* G0 SBCS forced to 7-bit output */
19457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len2 = MBCSSingleFromUChar32(myConverterData.myConverterArray[cs0], sourceChar, value, usingFallback);
19467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (len2 != 0 && !(len2 < 0 && len != 0) && GR96_START <= value[0] && value[0] <= GR96_END) {
19477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetValue = value[0] - 0x80;
19487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = len2;
19497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                cs = cs0;
19507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                g = 2;
19517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                usingFallback = false;
19527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
19537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
19547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        default :
19557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* G0 DBCS */
19567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.currentConverter.sharedData = myConverterData.myConverterArray[cs0];
19577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.currentConverter.sharedData.mbcs.outputType = CharsetMBCS.MBCS_OUTPUT_2;
19587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len2 = myConverterData.currentEncoder.fromUChar32(sourceChar, value, usingFallback);
19597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            //len2 = MBCSFromUChar32_ISO2022(myConverterData.myConverterArray[cs0], sourceChar, value, usingFallback, CharsetMBCS.MBCS_OUTPUT_2);
19607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (len2 == 2 || (len2 == -2 && len == 0)) { /* only accept DBCS: abs(len)==2 */
19617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (cs0 == KSC5601) {
19627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /*
19637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * Check for valid bytes for the encoding scheme.
19647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * This is necessary because the sub-converter (windows-949)
19657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     * has a broader encoding scheme than is valid for 2022.
19667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                     */
19677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    value[0] = _2022FromGR94DBCS(value[0]);
19687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (value[0] == 0) {
19697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        break;
19707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
19717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
19727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                targetValue = value[0];
19737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = len2;
19747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                cs = cs0;
19757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                g = 0;
19767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                usingFallback = false;
19777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
19787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
19797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
19807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
19812d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
19827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (len != 0) {
19837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (len < 0) {
19847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len = -len; /* fallback */
19857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
19867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        outLen = 0;
19872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
19887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* write SI if necessary (only for JIS7 */
19897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.fromU2022State.g == 1 && g == 0) {
19907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[outLen++] = UConverterConstants.SI;
19917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.fromU2022State.g = 0;
19927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
19932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
19947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* write the designation sequence if necessary */
19957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (cs != myConverterData.fromU2022State.cs[g]) {
19967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            for (int i = 0; i < escSeqChars[cs].length; i++) {
19977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                buffer[outLen++] = escSeqChars[cs][i];
19987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
19997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.fromU2022State.cs[g] = cs;
20002d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* invalidate the choices[] */
20027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            choiceCount = 0;
20037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
20042d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* write the shift sequence if necessary */
20067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (g != myConverterData.fromU2022State.g) {
20077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            switch (g) {
20087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* case 0 handled before writing escapes */
20097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            case 1:
20107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                buffer[outLen++] = UConverterConstants.SO;
20117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                myConverterData.fromU2022State.g = 1;
20127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
20137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            default : /* case 2 */
20147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                buffer[outLen++] = 0x1b;
20157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                buffer[outLen++] = 0x4e;
20167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
20177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* case 3: no SS3 in ISO-2022-JP-x */
20187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
20197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
20202d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* write the output bytes */
20227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (len == 1) {
20237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[outLen++] = (byte)targetValue;
20247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else { /* len == 2 */
20257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[outLen++] = (byte)(targetValue >> 8);
20267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[outLen++] = (byte)targetValue;
20277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
20287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }else {
20297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /*
20307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * if we cannot find the character after checking all codepages
20317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * then this is an error.
20327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
20337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CoderResult.unmappableForLength(source.position()-oldSourcePos);
20347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        fromUChar32 = sourceChar;
20357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
20367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
20372d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (sourceChar == CR || sourceChar == LF) {
20397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* reset the G2 state at the end of a line (conversion got use into ASCII or JISX201 already) */
20407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.fromU2022State.cs[2] = 0;
20417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        choiceCount = 0;
20427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
20432d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* output outLen>0 bytes in buffer[] */
20457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (outLen == 1) {
20467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put(buffer[0]);
20477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
20487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(source.remaining() - 1); /* -1 known to be ASCII */
20497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
20507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (outLen == 2 && (target.position() + 2) <= target.limit()) {
20517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put(buffer[0]);
20527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put(buffer[1]);
20537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
20547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int sourceIndex = source.position() - 1;
20557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(sourceIndex);
20567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(sourceIndex);
20577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
20587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
20597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CharsetEncoderICU.fromUWriteBytes(this, buffer, 0, outLen, target, offsets, source.position()-1);
20607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
20617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
20627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.OVERFLOW;
20637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
20647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
20657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
20662d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*
20687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * the end of the input stream and detection of truncated input
20697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * are handled by the framework, but for ISO-2022-JP conversion
20707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * we need to be in ASCII mode at the very end
20712d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert             *
20727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * conditions:
20737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *  successful
20747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *  in SO mode or not in ASCII mode
20757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *  end of input and no truncated input
20767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             */
20777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!err.isError() &&
20787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    (myConverterData.fromU2022State.g != 0 || myConverterData.fromU2022State.cs[0] != ASCII) &&
20797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    flush && !source.hasRemaining() && fromUChar32 == 0) {
20807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int sourceIndex;
20812d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                outLen = 0;
20832d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (myConverterData.fromU2022State.g != 0) {
20857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[outLen++] = UConverterConstants.SI;
20867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.fromU2022State.g = 0;
20877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
20882d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (myConverterData.fromU2022State.cs[0] != ASCII) {
20907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    for (int i = 0; i < escSeqChars[ASCII].length; i++) {
20917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        buffer[outLen++] = escSeqChars[ASCII][i];
20927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
20937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.fromU2022State.cs[0] = ASCII;
20947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
20952d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
20967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* get the source index of the last input character */
20977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                sourceIndex = source.position();
20987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (sourceIndex > 0) {
20997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    --sourceIndex;
21007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (UTF16.isTrailSurrogate(source.get(sourceIndex)) &&
21017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            (sourceIndex == 0 || UTF16.isLeadSurrogate(source.get(sourceIndex-1)))) {
21027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        --sourceIndex;
21037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
21047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
21057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sourceIndex = -1;
21067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
21072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
21087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = CharsetEncoderICU.fromUWriteBytes(this, buffer, 0, outLen, target, offsets, sourceIndex);
21097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
21107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
21117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
21127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
21137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /****************************ISO-2022-CN************************************/
21147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
21157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * Rules for ISO-2022-CN Encoding:
21167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * i)   The designator sequence must appear once on a line before any instance
21177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      of chracter set it designates.
21187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * ii)  If two lines contain characters from the same character set, both lines
21197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      must include the designator sequence.
21207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * iii) Once the designator sequence is known, a shifting sequence has to be found
21217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      to invoke the shifting
21227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * iv)  All lines start in ASCII and end in ASCII.
21237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     * v)   Four shifting sequences are employed for this purpose:
21247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      Sequence    ASCII Eq    Charsets
21257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ---------   ---------   --------
21267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SI          <SI>        US-ASCII
21277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SO          <SO>        CNS-11643-1992 Plane 1, GB2312, ISO-IR-165
21287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SS2         <ESC>N      CNS-11643-1992 Plane 2
21297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SS3         <ESC>O      CNS-11643-1992 Planes 3-7
21302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     * vi)
21317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SOdesignator    : ESC "$" ")" finalchar_for_SO
21327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SS2designator   : ESC "$" "*" finalchar_for_SS2
21337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      SS3designator   : ESC "$" "+" finalchar_for_SS3
21342d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ ) A       Indicates the bytes following SO are Chinese
21367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       characters as defined in GB 2312-80, until
21377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       another SOdesignation appears
21382d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ ) E       Indicates the bytes following SO are as defined
21407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       in ISO-IR-165 (for details, see section 2.1),
21417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       until another SOdesignation appears
21422d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ ) G       Indicates the bytes following SO are as defined
21447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       in CNS 11643-plane-1, until another SOdesignation appears
21452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ * H       Indicates teh two bytes immediately following
21477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       SS2 is a Chinese character as defined in CNS
21487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       11643-plane-2, until another SS2designation
21497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       appears
21507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       (Meaning <ESC>N must preceed ever 2 byte sequence.)
21512d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ + I       Indicates the immediate two bytes following SS3
21537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       is a Chinese character as defined in CNS
21547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       11643-plane-3, until another SS3designation
21557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       appears
21567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       (Meaning <ESC>O must preceed every 2 byte sequence.)
21572d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ + J       Indicates the immediate two bytes following SS3
21597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       is a Chinese character as defined in CNS
21607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       11643-plane-4, until another SS3designation
21617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       appears
21627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       (In English: <ESC>O must preceed every 2 byte sequence.)
21632d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ + K       Indicates the immediate two bytes following SS3
21657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       is a Chinese character as defined in CNS
21667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       11643-plane-5, until another SS3designation
21677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       appears
21682d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ + L       Indicates the immediate two bytes following SS3
21707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       is a Chinese character as defined in CNS
21717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       11643-plane-6, until another SS3designation
21727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       appears
21732d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      ESC $ + M       Indicates the immediate two bytes following SS3
21757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       is a Chinese character as defined in CNS
21767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       11643-plane-7, until another SS3designation
21777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *       appears
21782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert     *
21797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      As in ISO-2022-CN, each line starts in ASCII, and ends in ASCII, and
21807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      has its own designation information before any Chinese chracters
21817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      appears
21827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
21832d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
21847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /* The following are defined this way to make strings truely readonly */
21857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] GB_2312_80_STR = { 0x1B, 0x24, 0x29, 0x41 };
21867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] ISO_IR_165_STR = { 0x1B, 0x24, 0x29, 0x45 };
21877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_1_STR = { 0x1B, 0x24, 0x29, 0x47 };
21887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_2_STR = { 0x1B, 0x24, 0x2A, 0x48 };
21897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_3_STR = { 0x1B, 0x24, 0x2B, 0x49 };
21907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_4_STR = { 0x1B, 0x24, 0x2B, 0x4A };
21917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_5_STR = { 0x1B, 0x24, 0x2B, 0x4B };
21927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_6_STR = { 0x1B, 0x24, 0x2B, 0x4C };
21937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[] CNS_11643_1992_Plane_7_STR = { 0x1B, 0x24, 0x2B, 0x4D };
21942d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
21957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /************************ ISO2022-CN Data *****************************/
21967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private final static byte[][] escSeqCharsCN = {
21977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        SHIFT_IN_STR,
21987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        GB_2312_80_STR,
21997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        ISO_IR_165_STR,
22007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_1_STR,
22017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_2_STR,
22027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_3_STR,
22037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_4_STR,
22047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_5_STR,
22057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_6_STR,
22067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CNS_11643_1992_Plane_7_STR,
22077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    };
22082d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private class CharsetEncoderISO2022CN extends CharsetEncoderICU {
22107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public CharsetEncoderISO2022CN(CharsetICU cs) {
22117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(cs, fromUSubstitutionChar[0]);
22127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
22132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22142d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
22157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void implReset() {
22167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.implReset();
22177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.reset();
22187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
22192d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* This overrides the cbFromUWriteSub method in CharsetEncoderICU */
22212d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
22222d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        CoderResult cbFromUWriteSub (CharsetEncoderICU encoder,
22237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CharBuffer source, ByteBuffer target, IntBuffer offsets){
22247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
22257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] buffer = new byte[8];
22267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int i = 0;
22277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] subchar;
22287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            subchar = encoder.replacement();
22292d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.fromU2022State.g != 0) {
22317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* not in ASCII mode: switch to ASCII */
22327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.fromU2022State.g = 0;
22337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                buffer[i++] = UConverterConstants.SI;
22347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
22357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            buffer[i++] = subchar[0];
22362d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            err = CharsetEncoderICU.fromUWriteBytes(this, buffer, 0, i, target, offsets, source.position() - 1);
22387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
22397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
22407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
22412d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22422d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
22437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult encodeLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
22447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
22457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int sourceChar;
22467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] buffer = new byte[8];
22477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int len;
22487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] choices = new byte[3];
22497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int choiceCount;
22507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int targetValue = 0;
22517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean usingFallback;
22527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoGetTrail = false;
22537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int oldSourcePos; // For proper error handling
22542d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            choiceCount = 0;
22562d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* check if the last codepoint of previous buffer was a lead surrogate */
22587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if ((sourceChar = fromUChar32) != 0 && target.hasRemaining()) {
22597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                // goto getTrail label
22602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                gotoGetTrail = true;
22617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
22622d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (source.hasRemaining() || gotoGetTrail) {
22647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (target.hasRemaining() || gotoGetTrail) {
22657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    oldSourcePos = source.position();
22667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!gotoGetTrail) {
22677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        sourceChar = source.get();
22687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
22697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* check if the char is a First surrogate */
22707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (UTF16.isSurrogate((char)sourceChar) || gotoGetTrail) {
22717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (UTF16.isLeadSurrogate((char)sourceChar) || gotoGetTrail) {
22727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// getTrail label
22737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* reset gotoGetTrail flag*/
22747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             gotoGetTrail = false;
22752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
22767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* look ahead to find the trail surrogate */
22777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (source.hasRemaining()) {
22787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* test the following code unit */
22797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                char trail = source.get();
22807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                source.position(source.position()-1);
22817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (UTF16.isTrailSurrogate(trail)) {
22827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    source.get();
22837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    sourceChar = UCharacter.getCodePoint((char)sourceChar, trail);
22847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    fromUChar32 = 0x00;
22857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* convert this supplementary code point */
22867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* exit this condition tree */
22877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
22887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* this is an unmatched lead code unit (1st surrogate) */
22897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* callback(illegal) */
22907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    err = CoderResult.malformedForLength(1);
22917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    fromUChar32 = sourceChar;
22927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
22937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
22947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
22957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* no more input */
22967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                fromUChar32 = sourceChar;
22977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                break;
22987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
22997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
23007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* this is an unmatched trail code unit (2nd surrogate) */
23017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* callback(illegal) */
23027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.malformedForLength(1);
23037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            fromUChar32 = sourceChar;
23047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
23057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
23067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
23072d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* do the conversion */
23097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (sourceChar <= 0x007f) {
23107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* do not converter SO/SI/ESC */
23117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (IS_2022_CONTROL(sourceChar)) {
23127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* callback(illegal) */
23137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.malformedForLength(1);
23147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            fromUChar32 = sourceChar;
23157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
23167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
23172d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* US-ASCII */
23197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (myConverterData.fromU2022State.g == 0) {
23207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[0] = (byte)sourceChar;
23217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len = 1;
23227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
23237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[0] = UConverterConstants.SI;
23247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[1] = (byte)sourceChar;
23257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len = 2;
23267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.fromU2022State.g = 0;
23277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            choiceCount = 0;
23287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
23292d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (sourceChar == CR || sourceChar == LF) {
23317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* reset the state at the end of a line */
23327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            myConverterData.fromU2022State.reset();
23337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            choiceCount = 0;
23347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
23357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
23367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* convert U+0080..U+10ffff */
23377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        int i;
23387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        byte cs, g;
23392d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (choiceCount == 0) {
23417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* try the current SO/G1 converter first */
23427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            choices[0] = myConverterData.fromU2022State.cs[1];
23432d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* default to GB2312_1 if none is designated yet */
23457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (choices[0] == 0) {
23467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choices[0] = GB2312_1;
23477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
23487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (myConverterData.version == 0) {
23497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* ISO-2022-CN */
23507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* try other SO/G1 converter; a CNS_11643_1 lookup may result in any plane */
23517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (choices[0] == GB2312_1) {
23527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[1] = CNS_11643_1;
23537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
23547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[1] = GB2312_1;
23557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
23562d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choiceCount = 2;
23587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else if (myConverterData.version == 1) {
23597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* ISO-2022-CN-EXT */
23602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* try one of the other converters */
23627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                switch (choices[0]) {
23637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                case GB2312_1:
23647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[1] = CNS_11643_1;
23657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[2] = ISO_IR_165;
23667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
23677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                case ISO_IR_165:
23687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[1] = GB2312_1;
23697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[2] = CNS_11643_1;
23707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
23717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                default :
23727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[1] = GB2312_1;
23737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choices[2] = ISO_IR_165;
23747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
23757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
23762d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choiceCount = 3;
23787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
23797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* ISO-2022-CN-CNS */
23807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choices[0] = CNS_11643_1;
23817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choices[1] = GB2312_1;
23822d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                choiceCount = 2;
23847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
23857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
23862d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
23877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        cs = g = 0;
23887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /*
23897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * len==0:  no mapping found yet
23907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * len<0:   found a fallback result: continue looking for a roundtrip but no further fallbacks
23917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * len>0:   found a roundtrip result, done
23927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
23937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        len = 0;
23947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /*
23957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * We will turn off usingFallback after finding a fallback,
23967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * but we still get fallbacks from PUA code points as usual.
23977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * Therefore, we will also need to check that we don't overwrite
23987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * an early fallback with a later one.
23997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
24007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        usingFallback = useFallback;
24012d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
24027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        for (i = 0; i < choiceCount && len <= 0; ++i) {
24037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            byte cs0 = choices[i];
24047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (cs0 > 0) {
24057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                int[] value = new int[1];
24067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                int len2;
24077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (cs0 > CNS_11643_0) {
24087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.currentConverter.sharedData = myConverterData.myConverterArray[CNS_11643];
24097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.currentConverter.sharedData.mbcs.outputType = CharsetMBCS.MBCS_OUTPUT_3;
24107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    len2 = myConverterData.currentEncoder.fromUChar32(sourceChar, value, usingFallback);
24117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    //len2 = MBCSFromUChar32_ISO2022(myConverterData.myConverterArray[CNS_11643],
24127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    //        sourceChar, value, usingFallback, CharsetMBCS.MBCS_OUTPUT_3);
24137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (len2 == 3 || (len2 == -3 && len == 0)) {
24147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        targetValue = value[0];
24157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        cs = (byte)(CNS_11643_0 + (value[0] >> 16) - 0x80);
24167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        if (len2 >= 0) {
24177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            len = 2;
24187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        } else {
24197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            len = -2;
24207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            usingFallback = false;
24217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        }
24227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        if (cs == CNS_11643_1) {
24237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            g = 1;
24247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        } else if (cs == CNS_11643_2) {
24257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            g = 2;
24267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        } else if (myConverterData.version == 1) { /* plane 3..7 */
24277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            g = 3;
24287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        } else {
24297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            /* ISO-2022-CN (without -EXT) does not support plane 3..7 */
24307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                            len = 0;
24317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        }
24327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
24337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
24347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* GB2312_1 or ISO-IR-165 */
24357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.currentConverter.sharedData = myConverterData.myConverterArray[cs0];
24367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.currentConverter.sharedData.mbcs.outputType = CharsetMBCS.MBCS_OUTPUT_2;
24377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    len2 = myConverterData.currentEncoder.fromUChar32(sourceChar, value, usingFallback);
24387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    //len2 = MBCSFromUChar32_ISO2022(myConverterData.myConverterArray[cs0],
24397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    //        sourceChar, value, usingFallback, CharsetMBCS.MBCS_OUTPUT_2);
24407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (len2 == 2 || (len2 == -2 && len == 0)) {
24417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        targetValue = value[0];
24427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        len = len2;
24437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        cs = cs0;
24447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        g = 1;
24457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        usingFallback = false;
24467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
24477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
24487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
24497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
24502d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
24517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (len != 0) {
24527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            len = 0; /* count output bytes; it must have ben abs(len) == 2 */
24532d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
24547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* write the designation sequence if necessary */
24557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (cs != myConverterData.fromU2022State.cs[g]) {
24567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (cs < CNS_11643) {
24577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    for (int n = 0; n < escSeqCharsCN[cs].length; n++) {
24587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        buffer[n] = escSeqCharsCN[cs][n];
24597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
24607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
24617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    for (int n = 0; n < escSeqCharsCN[CNS_11643 + (cs - CNS_11643_1)].length; n++) {
24627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        buffer[n] = escSeqCharsCN[CNS_11643 + (cs - CNS_11643_1)][n];
24637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
24647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
24657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                len = 4;
24667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                myConverterData.fromU2022State.cs[g] = cs;
24677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (g == 1) {
24687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* changing the SO/G1 charset invalidates the choices[] */
24697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    choiceCount = 0;
24707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
24717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
24722d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
24737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* write the shift sequence if necessary */
24747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (g != myConverterData.fromU2022State.g) {
24757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                switch (g) {
24767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                case 1:
24777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    buffer[len++] = UConverterConstants.SO;
24782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
24797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* set the new state only if it is the locking shift SO/G1, not for SS2 or SS3 */
24807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    myConverterData.fromU2022State.g = 1;
24817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
24827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                case 2:
24837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    buffer[len++] = 0x1b;
24847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    buffer[len++] = 0x4e;
24857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
24867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                default: /* case 3 */
24877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    buffer[len++] = 0x1b;
24887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    buffer[len++] = 0x4f;
24897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    break;
24907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
24917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
24922d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
24937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* write the two output bytes */
24947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[len++] = (byte)(targetValue >> 8);
24957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            buffer[len++] = (byte)targetValue;
24967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
24977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* if we cannot find the character after checking all codepages
24987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             * then this is an error
24997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                             */
25007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.unmappableForLength(source.position()-oldSourcePos);
25017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            fromUChar32 = sourceChar;
25027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /* output len>0 bytes in buffer[] */
25067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (len == 1) {
25077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put(buffer[0]);
25087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
25097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(source.position()-1);
25107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else if (len == 2 && (target.remaining() >= 2)) {
25127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put(buffer[0]);
25137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        target.put(buffer[1]);
25147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (offsets != null) {
25157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            int sourceIndex = source.position();
25167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(sourceIndex);
25177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            offsets.put(sourceIndex);
25187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
25207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        err = CharsetEncoderICU.fromUWriteBytes(this, buffer, 0, len, target, offsets, source.position()-1);
25217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (err.isError()) {
25227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
25237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
25247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
25267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.OVERFLOW;
25277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
25287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
25297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            } /* end while (source.hasRemaining() */
25302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*
25327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * the end of the input stream and detection of truncated input
25337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * are handled by the framework, but for ISO-2022-CN conversion
25347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * we need to be in ASCII mode at the very end
25352d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert             *
25367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * condtions:
25377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *   succesful
25387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *   not in ASCII mode
25397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *   end of input and no truncated input
25407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             */
25417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!err.isError() && myConverterData.fromU2022State.g != 0 && flush && !source.hasRemaining() && fromUChar32 == 0) {
25427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int sourceIndex;
25432d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* we are switching to ASCII */
25457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.fromU2022State.g = 0;
25462d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* get the source index of the last input character */
25487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                sourceIndex = source.position();
25497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (sourceIndex > 0) {
25507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    --sourceIndex;
25512d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    if (UTF16.isTrailSurrogate(source.get(sourceIndex)) &&
25527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            (sourceIndex == 0 || UTF16.isLeadSurrogate(source.get(sourceIndex-1)))) {
25537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        --sourceIndex;
25547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
25557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
25567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sourceIndex = -1;
25577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
25582d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = CharsetEncoderICU.fromUWriteBytes(this, SHIFT_IN_STR, 0, 1, target, offsets, sourceIndex);
25607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
25612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
25637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
25647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
25657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /******************************** ISO-2022-KR *****************************/
25667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    /*
25677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *   Rules for ISO-2022-KR encoding
25687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *   i) The KSC5601 designator sequence should appear only once in a file,
25697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      at the begining of a line before any KSC5601 characters. This usually
25707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      means that it appears by itself on the first line of the file
25717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *  ii) There are only 2 shifting sequences SO to shift into double byte mode
25727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     *      and SI to shift into single byte mode
25737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert     */
25747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private class CharsetEncoderISO2022KR extends CharsetEncoderICU {
25757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        public CharsetEncoderISO2022KR(CharsetICU cs) {
25767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super(cs, fromUSubstitutionChar[myConverterData.version]);
25777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
25782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25792d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
25807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected void implReset() {
25817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            super.implReset();
25827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.reset();
25837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInitialStateFromUnicodeKR(this);
25847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
25852d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* This overrides the cbFromUWriteSub method in CharsetEncoderICU */
25872d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
25882d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        CoderResult cbFromUWriteSub (CharsetEncoderICU encoder,
25897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CharBuffer source, ByteBuffer target, IntBuffer offsets){
25907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
25917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] buffer = new byte[8];
25927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int length, i = 0;
25937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            byte[] subchar;
25942d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            subchar = encoder.replacement();
25967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            length = subchar.length;
25972d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
25987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.version == 0) {
25997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (length == 1) {
26007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (encoder.fromUnicodeStatus != 0) {
26017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* in DBCS mode: switch to SBCS */
26027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        encoder.fromUnicodeStatus = 0;
26037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        buffer[i++] = UConverterConstants.SI;
26047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
26057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = subchar[0];
26067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else { /* length == 2 */
26077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (encoder.fromUnicodeStatus == 0) {
26087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* in SBCS mode: switch to DBCS */
26097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        encoder.fromUnicodeStatus = 1;
26107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        buffer[i++] = UConverterConstants.SO;
26117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
26127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = subchar[0];
26137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    buffer[i++] = subchar[1];
26147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
26157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = CharsetEncoderICU.fromUWriteBytes(this, buffer, 0, i, target, offsets, source.position() - 1);
26162d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert            } else {
26177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* save the subvonverter's substitution string */
26187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                byte[] currentSubChars = myConverterData.currentEncoder.replacement();
26192d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* set our substitution string into the subconverter */
26217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.currentEncoder.replaceWith(subchar);
26227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.currentConverter.subChar1 = fromUSubstitutionChar[0][0];
26237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* let the subconverter write the subchar, set/retrieve fromUChar32 state */
26247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.currentEncoder.fromUChar32 = encoder.fromUChar32;
26257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                err = myConverterData.currentEncoder.cbFromUWriteSub(myConverterData.currentEncoder, source, target, offsets);
26267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                encoder.fromUChar32 = myConverterData.currentEncoder.fromUChar32;
26272d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* restore the subconverter's substitution string */
26297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.currentEncoder.replaceWith(currentSubChars);
26302d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (err.isOverflow()) {
26327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (myConverterData.currentEncoder.errorBufferLength > 0) {
26337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        encoder.errorBuffer = myConverterData.currentEncoder.errorBuffer.clone();
26347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
26357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    encoder.errorBufferLength = myConverterData.currentEncoder.errorBufferLength;
26367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    myConverterData.currentEncoder.errorBufferLength = 0;
26377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
26387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26392d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
26417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
26422d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        private CoderResult encodeLoopIBM(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
26447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
26457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
26467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentEncoder.fromUChar32 = fromUChar32;
26477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            err = myConverterData.currentEncoder.cnvMBCSFromUnicodeWithOffsets(source, target, offsets, flush);
26487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromUChar32 = myConverterData.currentEncoder.fromUChar32;
26492d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (err.isOverflow()) {
26517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (myConverterData.currentEncoder.errorBufferLength > 0) {
26527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    errorBuffer = myConverterData.currentEncoder.errorBuffer.clone();
26537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
26547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                errorBufferLength = myConverterData.currentEncoder.errorBufferLength;
26557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.currentEncoder.errorBufferLength = 0;
26567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26572d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
26597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
26602d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert        @Override
26627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        protected CoderResult encodeLoop(CharBuffer source, ByteBuffer target, IntBuffer offsets, boolean flush) {
26637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            CoderResult err = CoderResult.UNDERFLOW;
26647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int[] targetByteUnit = { 0x0000 };
26657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int sourceChar = 0x0000;
26667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean isTargetByteDBCS;
26677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean oldIsTargetByteDBCS;
26687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean usingFallback;
26697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int length = 0;
26707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            boolean gotoGetTrail = false; // for goto getTrail label call
26712d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*
26737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * if the version is 1 then the user is requesting
26747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * conversion with ibm-25546 pass the argument to
26757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * MBCS converter and return
26767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             */
26777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (myConverterData.version == 1) {
26787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                return encodeLoopIBM(source, target, offsets, flush);
26797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26802d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            usingFallback = useFallback;
26827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            isTargetByteDBCS = fromUnicodeStatus == 0 ? false : true;
26837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if ((sourceChar = fromUChar32) != 0 && target.hasRemaining()) {
26847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                gotoGetTrail = true;
26857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
26862d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            while (source.hasRemaining() || gotoGetTrail) {
26887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                targetByteUnit[0] = UConverterConstants.missingCharMarker;
26892d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (target.hasRemaining() || gotoGetTrail) {
26917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!gotoGetTrail) {
26927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        sourceChar = source.get();
26932d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
26947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* do not convert SO/SI/ESC */
26957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (IS_2022_CONTROL(sourceChar)) {
26967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* callback(illegal) */
26977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.malformedForLength(1);
26987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            fromUChar32 = sourceChar;
26997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            break;
27007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
27017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        myConverterData.currentConverter.sharedData.mbcs.outputType = CharsetMBCS.MBCS_OUTPUT_2;
27027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        length = myConverterData.currentEncoder.fromUChar32(sourceChar, targetByteUnit, usingFallback);
27032d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                        //length = MBCSFromUChar32_ISO2022(myConverterData.currentConverter.sharedData, sourceChar, targetByteUnit, usingFallback, CharsetMBCS.MBCS_OUTPUT_2);
27047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (length < 0) {
27057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            length = -length; /* fallback */
27067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
27077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* only DBCS or SBCS characters are expected */
27087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* DB characters with high bit set to 1 are expected */
27097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (length > 2 || length == 0 ||
27107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                (length == 1 && targetByteUnit[0] > 0x7f) ||
27117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                (length ==2 &&
27127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        ((char)(targetByteUnit[0] - 0xa1a1) > (0xfefe - 0xa1a1) ||
27137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        ((targetByteUnit[0] - 0xa1) & UConverterConstants.UNSIGNED_BYTE_MASK) > (0xfe - 0xa1)))) {
27147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            targetByteUnit[0] = UConverterConstants.missingCharMarker;
27157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
27167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
27177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (!gotoGetTrail && targetByteUnit[0] != UConverterConstants.missingCharMarker) {
27187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        oldIsTargetByteDBCS = isTargetByteDBCS;
27197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        isTargetByteDBCS = (targetByteUnit[0] > 0x00FF);
27207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* append the shift sequence */
27217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (oldIsTargetByteDBCS != isTargetByteDBCS) {
27227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (isTargetByteDBCS) {
27237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                target.put((byte)UConverterConstants.SO);
27247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
27257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                target.put((byte)UConverterConstants.SI);
27267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
27277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (offsets != null) {
27287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                offsets.put(source.position()-1);
27297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
27307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
27317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* write the targetUniChar to target */
27327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (targetByteUnit[0] <= 0x00FF) {
27337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (target.hasRemaining()) {
27347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                target.put((byte)targetByteUnit[0]);
27357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (offsets != null) {
27367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    offsets.put(source.position()-1);
27377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
27387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
27397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                errorBuffer[errorBufferLength++] = (byte)targetByteUnit[0];
27407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                err = CoderResult.OVERFLOW;
27417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
27427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
27437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (target.hasRemaining()) {
27447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                target.put((byte)(UConverterConstants.UNSIGNED_BYTE_MASK & ((targetByteUnit[0]>>8) - 0x80)));
27457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (offsets != null) {
27467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    offsets.put(source.position()-1);
27477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
27487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (target.hasRemaining()) {
27497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    target.put((byte)(UConverterConstants.UNSIGNED_BYTE_MASK & (targetByteUnit[0]- 0x80)));
27507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (offsets != null) {
27517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        offsets.put(source.position()-1);
27527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
27537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
27547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    errorBuffer[errorBufferLength++] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & (targetByteUnit[0] - 0x80));
27557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    err = CoderResult.OVERFLOW;
27567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
27572d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
27587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
27597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                errorBuffer[errorBufferLength++] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & ((targetByteUnit[0]>>8) - 0x80));
27607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                errorBuffer[errorBufferLength++] = (byte)(UConverterConstants.UNSIGNED_BYTE_MASK & (targetByteUnit[0]- 0x80));
27617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                err = CoderResult.OVERFLOW;
27627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
27637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
27647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    } else {
27657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* oops.. the code point is unassigned
27667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         * set the error and reason
27677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                         */
27682d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
27697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        /* check if the char is a First surrogate */
27707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        if (gotoGetTrail || UTF16.isSurrogate((char)sourceChar)) {
27717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            if (gotoGetTrail || UTF16.isLeadSurrogate((char)sourceChar)) {
27727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert// getTrail label
27737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                // reset gotoGetTrail flag
27747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                gotoGetTrail = false;
27752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
27767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* look ahead to find the trail surrogate */
27777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                if (source.hasRemaining()) {
27787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* test the following code unit */
27797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    char trail = source.get();
27807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    source.position(source.position()-1);
27817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    if (UTF16.isTrailSurrogate(trail)) {
27827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        source.get();
27837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                         sourceChar = UCharacter.getCodePoint((char)sourceChar, trail);
27847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                         err = CoderResult.unmappableForLength(2);
27857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                         /* convert this surrogate code point */
27867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                         /* exit this condition tree */
27877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    } else {
27887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        /* this is an unmatched lead code unit (1st surrogate) */
27897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        /* callback(illegal) */
27907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                        err = CoderResult.malformedForLength(1);
27917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    }
27927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                } else {
27937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    /* no more input */
27947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                    err = CoderResult.UNDERFLOW;
27957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                }
27967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            } else {
27977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* this is an unmatched trail code unit (2nd surrogate ) */
27987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                /* callback(illegal) */
27997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                                err = CoderResult.malformedForLength(1);
28007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            }
28017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        } else {
28027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            /* callback(unassigned) for a BMP code point */
28037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                            err = CoderResult.unmappableForLength(1);
28047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        }
28052d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        fromUChar32 = sourceChar;
28077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        break;
28087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
28097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
28107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    err = CoderResult.OVERFLOW;
28117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    break;
28127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
28137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
28147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*
28157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * the end of the input stream and detection of truncated input
28167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * are handled by the framework, but for ISO-2022-KR conversion
28177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * we need to be inASCII mode at the very end
28182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert             *
28197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * conditions:
28207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *  successful
28217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *  not in ASCII mode
28227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *  end of  input and no truncated input
28237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             */
28247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if (!err.isError() && isTargetByteDBCS && flush && !source.hasRemaining() && fromUChar32 == 0) {
28257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                int sourceIndex;
28262d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* we are switching to ASCII */
28287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                isTargetByteDBCS = false;
28292d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* get the source index of the last input character */
28317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                sourceIndex = source.position();
28327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if (sourceIndex > 0) {
28337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    --sourceIndex;
28347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    if (UTF16.isTrailSurrogate(source.get(sourceIndex)) && UTF16.isLeadSurrogate(source.get(sourceIndex-1))) {
28357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                        --sourceIndex;
28367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    }
28377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
28387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    sourceIndex = -1;
28397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
28402d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                CharsetEncoderICU.fromUWriteBytes(this, SHIFT_IN_STR, 0, 1, target, offsets, sourceIndex);
28427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
28437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*save the state and return */
28447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            fromUnicodeStatus = isTargetByteDBCS ? 1 : 0;
28452d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return err;
28477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28492d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28502d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Override
28517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CharsetDecoder newDecoder() {
28527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch (variant) {
28537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_JP:
28547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new CharsetDecoderISO2022JP(this);
28552d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_CN:
28577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new CharsetDecoderISO2022CN(this);
28582d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_KR:
28607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInitialStateToUnicodeKR();
28617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new CharsetDecoderISO2022KR(this);
28622d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        default: /* should not happen */
28647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
28657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28672d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28682d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Override
28697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    public CharsetEncoder newEncoder() {
28707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        CharsetEncoderICU cnv;
28712d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch (variant) {
28737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_JP:
28747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new CharsetEncoderISO2022JP(this);
28752d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_CN:
28777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return new CharsetEncoderISO2022CN(this);
28782d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_KR:
28807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv = new CharsetEncoderISO2022KR(this);
28817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setInitialStateFromUnicodeKR(cnv);
28827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return cnv;
28832d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        default: /* should not happen */
28857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            return null;
28867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28882d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
28897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void setInitialStateToUnicodeKR() {
28907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (myConverterData.version == 1) {
28917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentDecoder.toUnicodeStatus = 0;     /* offset */
28927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentDecoder.mode = 0;                /* state */
28937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentDecoder.toULength = 0;           /* byteIndex */
28947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
28957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
28967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    private void setInitialStateFromUnicodeKR(CharsetEncoderICU cnv) {
28977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* ISO-2022-KR the designator sequence appears only once
28987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * in a file so we append it only once
28997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
29007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (cnv.errorBufferLength == 0) {
29017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.errorBufferLength = 4;
29027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.errorBuffer[0] = 0x1b;
29037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.errorBuffer[1] = 0x24;
29047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.errorBuffer[2] = 0x29;
29057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            cnv.errorBuffer[3] = 0x43;
29067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        if (myConverterData.version == 1) {
29087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            ((CharsetMBCS)myConverterData.currentEncoder.charset()).subChar1 = 0x1A;
29097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentEncoder.fromUChar32 = 0;
29107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            myConverterData.currentEncoder.fromUnicodeStatus = 1; /* prevLength */
29117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
29132d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
29142d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert    @Override
29157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    void getUnicodeSetImpl(UnicodeSet setFillIn, int which) {
29167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        int i;
29177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*open a set and initialize it with code points that are algorithmically round-tripped */
29182d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
29197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        switch(variant){
29207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_JP:
29217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           /*include JIS X 0201 which is hardcoded */
29227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setFillIn.add(0xa5);
29237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setFillIn.add(0x203e);
29247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if((jpCharsetMasks[myConverterData.version]&CSM(ISO8859_1))!=0){
29257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /*include Latin-1 some variants of JP */
29267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setFillIn.add(0, 0xff);
29272d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
29287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            }
29297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            else {
29307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                /* include ASCII for JP */
29317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setFillIn.add(0, 0x7f);
29327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             }
29337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(myConverterData.version==3 || myConverterData.version==4 ||which == ROUNDTRIP_AND_FALLBACK_SET){
29347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /*
29357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * Do not test(jpCharsetMasks[myConverterData.version]&CSM(HWKANA_7BIT))!=0 because the bit
29367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * is on for all JP versions although version 3 & 4 (JIS7 and JIS8) use half-width Katakana.
29377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * This is because all ISO_2022_JP variant are lenient in that they accept (in toUnicode) half-width
29387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * Katakana via ESC.
29397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * However, we only emit (fromUnicode) half-width Katakana according to the
29407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * definition of each variant.
29417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             *
29427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * When including fallbacks,
29437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * we need to include half-width Katakana Unicode code points for all JP variants because
29447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             * JIS X 0208 has hardcoded fallbacks for them (which map to full-width Katakana).
29457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             */
29467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* include half-width Katakana for JP */
29477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                setFillIn.add(HWKANA_START, HWKANA_END);
29487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert             }
29497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
29507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_CN:
29517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* Include ASCII for CN */
29527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            setFillIn.add(0, 0x7f);
29537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
29547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        case ISO_2022_KR:
29557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            /* there is only one converter for KR */
29567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          myConverterData.currentConverter.getUnicodeSetImpl(setFillIn, which);
29577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert          break;
29587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        default:
29597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            break;
29607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29612d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
29627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        //TODO Replaced by ucnv_MBCSGetFilteredUnicodeSetForUnicode() until
29637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        for(i=0; i<UCNV_2022_MAX_CONVERTERS;i++){
29647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            int filter;
29657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert            if(myConverterData.myConverterArray[i]!=null){
29667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                if(variant==ISO_2022_CN && myConverterData.version==0 && i==CNS_11643){
29677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /*
29682d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                     *
29697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * version -specific for CN:
29707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * CN version 0 does not map CNS planes 3..7 although
29717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * they are all available in the CNS conversion table;
29727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * CN version 1 (-EXT) does map them all.
29737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * The two versions create different Unicode sets.
29747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     */
29757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    filter=CharsetMBCS.UCNV_SET_FILTER_2022_CN;
29767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if(variant==ISO_2022_JP && i == JISX208){
29772d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert                    /*
29787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * Only add code points that map to Shift-JIS codes
29797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * corrosponding to JIS X 208
29807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     */
29817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    filter=CharsetMBCS.UCNV_SET_FILTER_SJIS;
29827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else if(i==KSC5601){
29837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    /*
29847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * Some of the KSC 5601 tables (Convrtrs.txt has this aliases on multiple tables)
29857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     * are broader than GR94.
29867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                     */
29877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    filter=CharsetMBCS.UCNV_SET_FILTER_GR94DBCS;
29887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                } else {
29897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                    filter=CharsetMBCS.UCNV_SET_FILTER_NONE;
29907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                }
29912d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
29927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert                myConverterData.currentConverter.MBCSGetFilteredUnicodeSetForUnicode(myConverterData.myConverterArray[i],setFillIn, which, filter);
29937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert           }
29947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        }
29957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /*
29967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * ISO Converter must not convert SO/SI/ESC despite what sub-converters do by themselves
29977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         * Remove these characters from the set.
29987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert         */
29997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setFillIn.remove(0x0e);
30007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setFillIn.remove(0x0f);
30017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setFillIn.remove(0x1b);
30022d2bb24f747c65578da13d5b13b82f0669690461Fredrik Roubert
30037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        /* ISO 2022 converter do not convert C! controls either */
30047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert        setFillIn.remove(0x80, 0x9f);
30057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert    }
30067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert}
30077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
30157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert
3016