276 lines · 9.6 KB · Java
RawDownload
/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.io; /** * An algorithmic conversion from ISO 2022 to Unicode * * @author Tom Zhou */public abstract class ByteToCharISO2022 extends ByteToCharConverter{    // Value to be filled by subclass    protected String SODesignator[];    protected String SS2Designator[] = null;    protected String SS3Designator[] = null;     protected ByteToCharConverter SOConverter[];    protected ByteToCharConverter SS2Converter[] = null;    protected ByteToCharConverter SS3Converter[] = null;     private static final byte ISO_ESC = 0x1b;    private static final byte ISO_SI = 0x0f;    private static final byte ISO_SO = 0x0e;    private static final byte ISO_SS2_7 = 0x4e;    private static final byte ISO_SS3_7 = 0x4f;    private static final byte MSB = (byte)0x80;    private static final char REPLACE_CHAR = '\uFFFD';    private static final byte maximumDesignatorLength = 3;     private static final byte SOFlag = 0;    private static final byte SS2Flag = 1;    private static final byte SS3Flag = 2;    private static final byte G0 = 0;    private static final byte G1 = 1;     private ByteToCharConverter tmpConverter[];     private int curSODes, curSS2Des, curSS3Des;    private boolean shiftout;     private byte remainByte[] = new byte[10];    private int remainIndex = -1;    private byte state, firstByte;     public void reset()    {        int i = 0;         shiftout = false;        state = G0;        firstByte = 0;         curSODes = 0;        curSS2Des = 0;        curSS3Des = 0;         charOff = byteOff = 0;        remainIndex = -1;         for(i = 0; i < remainByte.length; i++)            remainByte[i] = 0;    }     public int flush(char[] output, int outStart, int outEnd)        throws MalformedInputException    {        int i;        if (state != G0) {            badInputLength = 0;            throw new MalformedInputException();        }        reset();        return 0;    }     private byte[] savetyGetSrc(byte[] input, int inOff, int inEnd, int nbytes)    {        int i;        byte tmp[];         if(inOff <= (inEnd-nbytes+1))            tmp = new byte[nbytes];        else            tmp = new byte[inEnd-inOff];         for(i = 0; i < tmp.length; i++)            tmp[i] = input[inOff+i];        return tmp;    }     private char getUnicode(byte byte1, byte byte2, byte shiftFlag)    {        byte1 |= MSB;        byte2 |= MSB;         byte[] tmpByte = {byte1,byte2};        char[] tmpChar = new char[1];        int     i = 0,                tmpIndex = 0;         switch(shiftFlag) {        case SOFlag:            tmpIndex = curSODes;            tmpConverter = SOConverter;            break;        case SS2Flag:            tmpIndex = curSS2Des;            tmpConverter = SS2Converter;            break;        case SS3Flag:            tmpIndex = curSS3Des;            tmpConverter = SS3Converter;            break;        }         for(i = 0; i < tmpConverter.length; i++) {            if(tmpIndex == i) {                try {                    tmpConverter[i].convert(tmpByte, 0, 2, tmpChar, 0, 1);                } catch (Exception e) {}                return tmpChar[0];            }        }        return REPLACE_CHAR;    }     public final int convert(byte[] input, int inOff, int inEnd,                             char[] output, int outOff, int outEnd)                             throws ConversionBufferFullException,                                    MalformedInputException    {        int i;        int DesignatorLength = 0;        charOff  =  outOff;        byteOff  =  inOff;         // Loop until we hit the end of the input        while (byteOff < inEnd) {            // If we don't have room for the output, throw an exception            if (charOff >= outEnd)                throw new ConversionBufferFullException();            if(remainIndex < 0) {                remainByte[0] = input[byteOff];                remainIndex = 0;                byteOff++;            }            switch (remainByte[0]) {            case ISO_SO:                shiftout = true;                if(remainIndex > 0)                    System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);                remainIndex--;                break;            case ISO_SI:                shiftout = false;                if(remainIndex > 0)                    System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);                remainIndex--;                break;             case ISO_ESC:                byte tmp[] = savetyGetSrc(input, byteOff, inEnd,                               (maximumDesignatorLength-remainIndex));                System.arraycopy(tmp, 0, remainByte, remainIndex+1, tmp.length);                remainIndex += tmp.length;                byteOff += tmp.length;                if(tmp.length<(maximumDesignatorLength-remainIndex))                    break;                String tmpString = new String(remainByte, 1, remainIndex);                for (i = 0; i < SODesignator.length; i++) {                    if(tmpString.indexOf(SODesignator[i]) == 0) {                        curSODes = i;                        DesignatorLength = SODesignator[i].length();                        break;                    }                }                 if (DesignatorLength == 0 ) { // Designator not recognized                   badInputLength = tmp.length;                   throw new MalformedInputException();                }                 if (i == SODesignator.length) {                    for (i = 0; i < SS2Designator.length; i++) {                        if(tmpString.indexOf(SS2Designator[i]) == 0) {                            curSS2Des = i;                            DesignatorLength = SS2Designator[i].length();                            break;                        }                    }                    if(i == SS2Designator.length) {                        for(i = 0; i < SS3Designator.length; i++) {                            if (tmpString.indexOf(SS3Designator[i]) == 0) {                                curSS3Des = i;                                DesignatorLength = SS3Designator[i].length();                                break;                            }                        }                        if (i == SS3Designator.length) {                            switch(remainByte[1]) {                            case ISO_SS2_7:                                output[charOff] = getUnicode(remainByte[2],                                                          remainByte[3],                                                          SS2Flag);                                charOff++;                                DesignatorLength = 3;                                break;                            case ISO_SS3_7:                                output[charOff] = getUnicode(remainByte[2],                                                          remainByte[3],                                                          SS3Flag);                                charOff++;                                DesignatorLength = 3;                                break;                            default:                                DesignatorLength = 0;                            }                        }                    }                }                if (remainIndex > DesignatorLength) {                    for(i = 0; i < remainIndex-DesignatorLength; i++)                        remainByte[i] = remainByte[DesignatorLength+1+i];                    remainIndex = i-1;                } else {                    remainIndex = -1;                }                break;            default:                if (!shiftout) {                    output[charOff] = (char)remainByte[0];                    charOff++;                } else {                    switch (state) {                    case G0:                        firstByte = remainByte[0];                        state = G1;                        break;                    case G1:                        output[charOff] = getUnicode(firstByte, remainByte[0],                                                  SOFlag);                        charOff++;                        state = G0;                        break;                    }                }                if (remainIndex > 0)                    System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);                remainIndex--;            }        }        return charOff - outOff;    }}