/*
* @(#)ByteToCharISO2022.java 1.11 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* This program 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 at /legal/license.txt).
*
* 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 or visit www.sun.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 = (ByteToCharConverter[]) SOConverter;
break;
case SS2Flag:
tmpIndex = curSS2Des;
tmpConverter = (ByteToCharConverter[]) SS2Converter;
break;
case SS3Flag:
tmpIndex = curSS3Des;
tmpConverter = (ByteToCharConverter[]) 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 {
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 (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;
}
}