001: /*
002: * @(#)ByteToCharISO2022.java 1.11 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.io;
029:
030: /**
031: * An algorithmic conversion from ISO 2022 to Unicode
032: *
033: * @author Tom Zhou
034: */
035: public abstract class ByteToCharISO2022 extends ByteToCharConverter {
036: // Value to be filled by subclass
037: protected String SODesignator[];
038: protected String SS2Designator[] = null;
039: protected String SS3Designator[] = null;
040: protected ByteToCharConverter SOConverter[];
041: protected ByteToCharConverter SS2Converter[] = null;
042: protected ByteToCharConverter SS3Converter[] = null;
043: private static final byte ISO_ESC = 0x1b;
044: private static final byte ISO_SI = 0x0f;
045: private static final byte ISO_SO = 0x0e;
046: private static final byte ISO_SS2_7 = 0x4e;
047: private static final byte ISO_SS3_7 = 0x4f;
048: private static final byte MSB = (byte) 0x80;
049: private static final char REPLACE_CHAR = '\uFFFD';
050: private static final byte maximumDesignatorLength = 3;
051: private static final byte SOFlag = 0;
052: private static final byte SS2Flag = 1;
053: private static final byte SS3Flag = 2;
054: private static final byte G0 = 0;
055: private static final byte G1 = 1;
056: private ByteToCharConverter tmpConverter[];
057: private int curSODes, curSS2Des, curSS3Des;
058: private boolean shiftout;
059: private byte remainByte[] = new byte[10];
060: private int remainIndex = -1;
061: private byte state, firstByte;
062:
063: public void reset() {
064: int i = 0;
065: shiftout = false;
066: state = G0;
067: firstByte = 0;
068: curSODes = 0;
069: curSS2Des = 0;
070: curSS3Des = 0;
071: charOff = byteOff = 0;
072: remainIndex = -1;
073: for (i = 0; i < remainByte.length; i++)
074: remainByte[i] = 0;
075: }
076:
077: public int flush(char[] output, int outStart, int outEnd)
078: throws MalformedInputException {
079: int i;
080: if (state != G0) {
081: badInputLength = 0;
082: throw new MalformedInputException();
083: }
084: reset();
085: return 0;
086: }
087:
088: private byte[] savetyGetSrc(byte[] input, int inOff, int inEnd,
089: int nbytes) {
090: int i;
091: byte tmp[];
092: if (inOff <= (inEnd - nbytes + 1))
093: tmp = new byte[nbytes];
094: else
095: tmp = new byte[inEnd - inOff];
096: for (i = 0; i < tmp.length; i++)
097: tmp[i] = input[inOff + i];
098: return tmp;
099: }
100:
101: private char getUnicode(byte byte1, byte byte2, byte shiftFlag) {
102: byte1 |= MSB;
103: byte2 |= MSB;
104: byte[] tmpByte = { byte1, byte2 };
105: char[] tmpChar = new char[1];
106: int i = 0, tmpIndex = 0;
107: switch (shiftFlag) {
108: case SOFlag:
109: tmpIndex = curSODes;
110: tmpConverter = (ByteToCharConverter[]) SOConverter;
111: break;
112:
113: case SS2Flag:
114: tmpIndex = curSS2Des;
115: tmpConverter = (ByteToCharConverter[]) SS2Converter;
116: break;
117:
118: case SS3Flag:
119: tmpIndex = curSS3Des;
120: tmpConverter = (ByteToCharConverter[]) SS3Converter;
121: break;
122: }
123: for (i = 0; i < tmpConverter.length; i++) {
124: if (tmpIndex == i) {
125: try {
126: tmpConverter[i].convert(tmpByte, 0, 2, tmpChar, 0,
127: 1);
128: } catch (Exception e) {
129: }
130: return tmpChar[0];
131: }
132: }
133: return REPLACE_CHAR;
134: }
135:
136: public final int convert(byte[] input, int inOff, int inEnd,
137: char[] output, int outOff, int outEnd)
138: throws ConversionBufferFullException {
139: int i;
140: int DesignatorLength = 0;
141: charOff = outOff;
142: byteOff = inOff;
143: // Loop until we hit the end of the input
144: while (byteOff < inEnd) {
145: // If we don't have room for the output, throw an exception
146: if (charOff >= outEnd)
147: throw new ConversionBufferFullException();
148: if (remainIndex < 0) {
149: remainByte[0] = input[byteOff];
150: remainIndex = 0;
151: byteOff++;
152: }
153: switch (remainByte[0]) {
154: case ISO_SO:
155: shiftout = true;
156: if (remainIndex > 0)
157: System.arraycopy(remainByte, 1, remainByte, 0,
158: remainIndex);
159: remainIndex--;
160: break;
161:
162: case ISO_SI:
163: shiftout = false;
164: if (remainIndex > 0)
165: System.arraycopy(remainByte, 1, remainByte, 0,
166: remainIndex);
167: remainIndex--;
168: break;
169:
170: case ISO_ESC:
171: byte tmp[] = savetyGetSrc(input, byteOff, inEnd,
172: (maximumDesignatorLength - remainIndex));
173: System.arraycopy(tmp, 0, remainByte, remainIndex + 1,
174: tmp.length);
175: remainIndex += tmp.length;
176: byteOff += tmp.length;
177: if (tmp.length < (maximumDesignatorLength - remainIndex))
178: break;
179: String tmpString = new String(remainByte, 1,
180: remainIndex);
181: for (i = 0; i < SODesignator.length; i++) {
182: if (tmpString.indexOf(SODesignator[i]) == 0) {
183: curSODes = i;
184: DesignatorLength = SODesignator[i].length();
185: break;
186: }
187: }
188: if (i == SODesignator.length) {
189: for (i = 0; i < SS2Designator.length; i++) {
190: if (tmpString.indexOf(SS2Designator[i]) == 0) {
191: curSS2Des = i;
192: DesignatorLength = SS2Designator[i]
193: .length();
194: break;
195: }
196: }
197: if (i == SS2Designator.length) {
198: for (i = 0; i < SS3Designator.length; i++) {
199: if (tmpString.indexOf(SS3Designator[i]) == 0) {
200: curSS3Des = i;
201: DesignatorLength = SS3Designator[i]
202: .length();
203: break;
204: }
205: }
206: if (i == SS3Designator.length) {
207: switch (remainByte[1]) {
208: case ISO_SS2_7:
209: output[charOff] = getUnicode(
210: remainByte[2], remainByte[3],
211: SS2Flag);
212: charOff++;
213: DesignatorLength = 3;
214: break;
215:
216: case ISO_SS3_7:
217: output[charOff] = getUnicode(
218: remainByte[2], remainByte[3],
219: SS3Flag);
220: charOff++;
221: DesignatorLength = 3;
222: break;
223:
224: default:
225: DesignatorLength = 0;
226: }
227: }
228: }
229: }
230: if (remainIndex > DesignatorLength) {
231: for (i = 0; i < remainIndex - DesignatorLength; i++)
232: remainByte[i] = remainByte[DesignatorLength + 1
233: + i];
234: remainIndex = i - 1;
235: } else {
236: remainIndex = -1;
237: }
238: break;
239:
240: default:
241: if (!shiftout) {
242: output[charOff] = (char) remainByte[0];
243: charOff++;
244: } else {
245: switch (state) {
246: case G0:
247: firstByte = remainByte[0];
248: state = G1;
249: break;
250:
251: case G1:
252: output[charOff] = getUnicode(firstByte,
253: remainByte[0], SOFlag);
254: charOff++;
255: state = G0;
256: break;
257: }
258: }
259: if (remainIndex > 0)
260: System.arraycopy(remainByte, 1, remainByte, 0,
261: remainIndex);
262: remainIndex--;
263: }
264: }
265: return charOff - outOff;
266: }
267: }
|