239 lines · 9.0 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; import java.io.UnsupportedEncodingException;import sun.nio.cs.ext.JISAutoDetect; public class ByteToCharJISAutoDetect extends ByteToCharConverter {     private final static int EUCJP_MASK = 0x01;    private final static int SJIS2B_MASK = 0x02;    private final static int SJIS1B_MASK = 0x04;    private final static int EUCJP_KANA1_MASK = 0x08;    private final static int EUCJP_KANA2_MASK = 0x10;    private final static byte[] maskTable1 = JISAutoDetect.getByteMask1();    private final static byte[] maskTable2 = JISAutoDetect.getByteMask2();     private final static int SS2 = 0x8e;    private final static int SS3 = 0x8f;     // SJISName is set to either "SJIS" or "MS932"    private String SJISName;    private String EUCJPName;     private String convName = null;    private ByteToCharConverter detectedConv = null;    private ByteToCharConverter defaultConv = null;     public ByteToCharJISAutoDetect() {        super();        SJISName = CharacterEncoding.getSJISName();        EUCJPName = CharacterEncoding.getEUCJPName();        defaultConv = new ByteToCharISO8859_1();        defaultConv.subChars = subChars;        defaultConv.subMode = subMode;    }     public int flush(char [] output, int outStart, int outEnd)        throws MalformedInputException, ConversionBufferFullException    {        badInputLength = 0;        if(detectedConv != null)             return detectedConv.flush(output, outStart, outEnd);        else             return defaultConv.flush(output, outStart, outEnd);    }      /**     * Character conversion     */    public int convert(byte[] input, int inOff, int inEnd,                       char[] output, int outOff, int outEnd)        throws UnknownCharacterException, MalformedInputException,               ConversionBufferFullException    {        int num = 0;         charOff = outOff;        byteOff = inOff;         try {            if (detectedConv == null) {                int euckana = 0;                int ss2count = 0;                int firstmask = 0;                int secondmask = 0;                int cnt;                boolean nonAsciiFound = false;                 for (cnt = inOff; cnt < inEnd; cnt++) {                    firstmask = 0;                    secondmask = 0;                    int byte1 = input[cnt]&0xff;                    int byte2;                     // TODO: should check valid escape sequences!                    if (byte1 == 0x1b) {                        convName = "ISO2022JP";                        break;                    }                     // Try to convert all leading ASCII characters.                    if ((nonAsciiFound == false) && (byte1 < 0x80)) {                        if (charOff >= outEnd)                            throw new ConversionBufferFullException();                        output[charOff++] = (char) byte1;                        byteOff++;                        num++;                        continue;                    }                     // We can no longer convert ASCII.                    nonAsciiFound = true;                     firstmask = maskTable1[byte1];                    if (byte1 == SS2)                        ss2count++;                     if (firstmask != 0) {                        if (cnt+1 < inEnd) {                            byte2 = input[++cnt] & 0xff;                            secondmask = maskTable2[byte2];                            int mask = firstmask & secondmask;                            if (mask == EUCJP_MASK) {                                convName = EUCJPName;                                break;                            }                            if ((mask == SJIS2B_MASK) || (mask == SJIS1B_MASK)                                || (JISAutoDetect.canBeSJIS1B(firstmask) && secondmask == 0)) {                                convName = SJISName;                                break;                            }                             // If the first byte is a SS3 and the third byte                            // is not an EUC byte, it should be SJIS.                            // Otherwise, we can't determine it yet, but it's                            // very likely SJIS. So we don't take the EUCJP CS3                            // character boundary. If we tried both                            // possibilities here, it might be able to be                            // determined correctly.                            if ((byte1 == SS3) && JISAutoDetect.canBeEUCJP(secondmask)) {                                if (cnt+1 < inEnd) {                                    int nextbyte = input[cnt+1] & 0xff;                                    if (! JISAutoDetect.canBeEUCJP(maskTable2[nextbyte]))                                        convName = SJISName;                                } else                                    convName = SJISName;                            }                            if (JISAutoDetect.canBeEUCKana(firstmask, secondmask))                                euckana++;                        } else {                            if ((firstmask & SJIS1B_MASK) != 0) {                                convName = SJISName;                                break;                            }                        }                    }                }                 if (nonAsciiFound && (convName == null)) {                    if ((euckana > 1) || (ss2count > 1))                        convName = EUCJPName;                    else                        convName = SJISName;                }                 if (convName != null) {                    try {                        detectedConv = ByteToCharConverter.getConverter(convName);                        detectedConv.subChars = subChars;                        detectedConv.subMode = subMode;                    } catch (UnsupportedEncodingException e){                        detectedConv = null;                        convName = null;                    }                }            }        } catch (ConversionBufferFullException bufferFullException) {                throw bufferFullException;        } catch (Exception e) {            // If we fail to detect the converter needed for any reason,            // use the default converter.            detectedConv = defaultConv;        }         // If we've converted all ASCII characters, then return.        if (byteOff == inEnd) {            return num;        }         if(detectedConv != null) {            try {                num += detectedConv.convert(input, inOff + num, inEnd,                                            output, outOff + num, outEnd);            } finally {                charOff = detectedConv.nextCharIndex();                byteOff = detectedConv.nextByteIndex();                badInputLength = detectedConv.badInputLength;            }        } else {            try {                num += defaultConv.convert(input, inOff + num, inEnd,                                           output, outOff + num, outEnd);            } finally {                charOff = defaultConv.nextCharIndex();                byteOff = defaultConv.nextByteIndex();                badInputLength = defaultConv.badInputLength;            }        }        return num;    }     public void reset() {        if(detectedConv != null) {             detectedConv.reset();             detectedConv = null;             convName = null;        } else             defaultConv.reset();        charOff = byteOff = 0;    }     public String getCharacterEncoding() {        return "JISAutoDetect";    }     public String toString() {        String s = getCharacterEncoding();        if (detectedConv != null) {            s += "[" + detectedConv.getCharacterEncoding() + "]";        } else {            s += "[unknown]";        }        return s;    }}