| /* |
| * Copyright 1997-2001 Sun Microsystems, Inc. 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. Sun designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| */ |
| |
| package sun.io; |
| |
| /** |
| * @author Tom Zhou |
| */ |
| public class ByteToCharISO2022CN extends ByteToCharConverter |
| { |
| private String SODesignator[]; |
| private String SS2Designator[] = null; |
| private String SS3Designator[] = null; |
| private ByteToCharConverter SOConverter[]; |
| private ByteToCharConverter SS2Converter[] = null; |
| private 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; |
| char[] tmpChar = new char[1]; |
| |
| switch(shiftFlag) { |
| case SOFlag: |
| try { |
| byte[] tmpByte = {byte1,byte2}; |
| SOConverter[curSODes].convert(tmpByte, 0, 2, tmpChar, 0, 1); |
| } |
| catch (Exception e) {} |
| break; |
| case SS2Flag: |
| try { |
| byte[] tmpByte = {(byte)0x8e, (byte)0xa2, byte1, byte2}; |
| SS2Converter[curSS2Des].convert(tmpByte, 0, 4, tmpChar, 0, 1); |
| } |
| catch (Exception e){} |
| break; |
| case SS3Flag: |
| try { |
| byte[] tmpByte = {(byte)0x8e, (byte)0xa3, byte1,byte2}; |
| SS3Converter[curSS3Des].convert(tmpByte, 0, 4, tmpChar, 0, 1); |
| } |
| catch (Exception e){} |
| break; |
| default: |
| tmpChar[0] = REPLACE_CHAR; |
| } |
| return tmpChar[0]; |
| } |
| |
| 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; |
| } |
| |
| public ByteToCharISO2022CN() |
| { |
| SODesignator = new String[3]; |
| SODesignator[0] = "$A"; |
| SODesignator[1] = "$)A"; |
| SODesignator[2] = "$)G"; |
| SS2Designator = new String[1]; |
| SS2Designator[0] = "$*H"; |
| SS3Designator = new String[1]; |
| SS3Designator[0] = "$+I"; |
| |
| SOConverter = new ByteToCharConverter[3]; |
| SS2Converter = new ByteToCharConverter[1]; |
| SS3Converter = new ByteToCharConverter[1]; |
| |
| try { |
| SOConverter[0] = SOConverter[1] |
| = ByteToCharConverter.getConverter("GB2312"); |
| SOConverter[2] = SS2Converter[0] = SS3Converter[0] |
| = ByteToCharConverter.getConverter("CNS11643"); |
| } catch (Exception e) {}; |
| } |
| |
| // Return the character set id |
| public String getCharacterEncoding() |
| { |
| return "ISO2022CN"; |
| } |
| } |