blob: 487121c5c0fc16dadf28fe6c1b8f765e5baf28dd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-2001 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.io;
27
28/**
29 * An algorithmic conversion from ISO 2022 to Unicode
30 *
31 * @author Tom Zhou
32 */
33public abstract class ByteToCharISO2022 extends ByteToCharConverter
34{
35 // Value to be filled by subclass
36 protected String SODesignator[];
37 protected String SS2Designator[] = null;
38 protected String SS3Designator[] = null;
39
40 protected ByteToCharConverter SOConverter[];
41 protected ByteToCharConverter SS2Converter[] = null;
42 protected ByteToCharConverter SS3Converter[] = null;
43
44 private static final byte ISO_ESC = 0x1b;
45 private static final byte ISO_SI = 0x0f;
46 private static final byte ISO_SO = 0x0e;
47 private static final byte ISO_SS2_7 = 0x4e;
48 private static final byte ISO_SS3_7 = 0x4f;
49 private static final byte MSB = (byte)0x80;
50 private static final char REPLACE_CHAR = '\uFFFD';
51 private static final byte maximumDesignatorLength = 3;
52
53 private static final byte SOFlag = 0;
54 private static final byte SS2Flag = 1;
55 private static final byte SS3Flag = 2;
56 private static final byte G0 = 0;
57 private static final byte G1 = 1;
58
59 private ByteToCharConverter tmpConverter[];
60
61 private int curSODes, curSS2Des, curSS3Des;
62 private boolean shiftout;
63
64 private byte remainByte[] = new byte[10];
65 private int remainIndex = -1;
66 private byte state, firstByte;
67
68 public void reset()
69 {
70 int i = 0;
71
72 shiftout = false;
73 state = G0;
74 firstByte = 0;
75
76 curSODes = 0;
77 curSS2Des = 0;
78 curSS3Des = 0;
79
80 charOff = byteOff = 0;
81 remainIndex = -1;
82
83 for(i = 0; i < remainByte.length; i++)
84 remainByte[i] = 0;
85 }
86
87 public int flush(char[] output, int outStart, int outEnd)
88 throws MalformedInputException
89 {
90 int i;
91 if (state != G0) {
92 badInputLength = 0;
93 throw new MalformedInputException();
94 }
95 reset();
96 return 0;
97 }
98
99 private byte[] savetyGetSrc(byte[] input, int inOff, int inEnd, int nbytes)
100 {
101 int i;
102 byte tmp[];
103
104 if(inOff <= (inEnd-nbytes+1))
105 tmp = new byte[nbytes];
106 else
107 tmp = new byte[inEnd-inOff];
108
109 for(i = 0; i < tmp.length; i++)
110 tmp[i] = input[inOff+i];
111 return tmp;
112 }
113
114 private char getUnicode(byte byte1, byte byte2, byte shiftFlag)
115 {
116 byte1 |= MSB;
117 byte2 |= MSB;
118
119 byte[] tmpByte = {byte1,byte2};
120 char[] tmpChar = new char[1];
121 int i = 0,
122 tmpIndex = 0;
123
124 switch(shiftFlag) {
125 case SOFlag:
126 tmpIndex = curSODes;
127 tmpConverter = (ByteToCharConverter [])SOConverter;
128 break;
129 case SS2Flag:
130 tmpIndex = curSS2Des;
131 tmpConverter = (ByteToCharConverter [])SS2Converter;
132 break;
133 case SS3Flag:
134 tmpIndex = curSS3Des;
135 tmpConverter = (ByteToCharConverter [])SS3Converter;
136 break;
137 }
138
139 for(i = 0; i < tmpConverter.length; i++) {
140 if(tmpIndex == i) {
141 try {
142 tmpConverter[i].convert(tmpByte, 0, 2, tmpChar, 0, 1);
143 } catch (Exception e) {}
144 return tmpChar[0];
145 }
146 }
147 return REPLACE_CHAR;
148 }
149
150 public final int convert(byte[] input, int inOff, int inEnd,
151 char[] output, int outOff, int outEnd)
152 throws ConversionBufferFullException,
153 MalformedInputException
154 {
155 int i;
156 int DesignatorLength = 0;
157 charOff = outOff;
158 byteOff = inOff;
159
160 // Loop until we hit the end of the input
161 while (byteOff < inEnd) {
162 // If we don't have room for the output, throw an exception
163 if (charOff >= outEnd)
164 throw new ConversionBufferFullException();
165 if(remainIndex < 0) {
166 remainByte[0] = input[byteOff];
167 remainIndex = 0;
168 byteOff++;
169 }
170 switch (remainByte[0]) {
171 case ISO_SO:
172 shiftout = true;
173 if(remainIndex > 0)
174 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
175 remainIndex--;
176 break;
177 case ISO_SI:
178 shiftout = false;
179 if(remainIndex > 0)
180 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
181 remainIndex--;
182 break;
183 case ISO_ESC:
184 byte tmp[] = savetyGetSrc(input, byteOff, inEnd,
185 (maximumDesignatorLength-remainIndex));
186 System.arraycopy(tmp, 0, remainByte, remainIndex+1, tmp.length);
187 remainIndex += tmp.length;
188 byteOff += tmp.length;
189 if(tmp.length<(maximumDesignatorLength-remainIndex))
190 break;
191 String tmpString = new String(remainByte, 1, remainIndex);
192 for (i = 0; i < SODesignator.length; i++) {
193 if(tmpString.indexOf(SODesignator[i]) == 0) {
194 curSODes = i;
195 DesignatorLength = SODesignator[i].length();
196 break;
197 }
198 }
199
200 if (DesignatorLength == 0 ) { // Designator not recognized
201 badInputLength = tmp.length;
202 throw new MalformedInputException();
203 }
204
205 if (i == SODesignator.length) {
206 for (i = 0; i < SS2Designator.length; i++) {
207 if(tmpString.indexOf(SS2Designator[i]) == 0) {
208 curSS2Des = i;
209 DesignatorLength = SS2Designator[i].length();
210 break;
211 }
212 }
213 if(i == SS2Designator.length) {
214 for(i = 0; i < SS3Designator.length; i++) {
215 if (tmpString.indexOf(SS3Designator[i]) == 0) {
216 curSS3Des = i;
217 DesignatorLength = SS3Designator[i].length();
218 break;
219 }
220 }
221 if (i == SS3Designator.length) {
222 switch(remainByte[1]) {
223 case ISO_SS2_7:
224 output[charOff] = getUnicode(remainByte[2],
225 remainByte[3],
226 SS2Flag);
227 charOff++;
228 DesignatorLength = 3;
229 break;
230 case ISO_SS3_7:
231 output[charOff] = getUnicode(remainByte[2],
232 remainByte[3],
233 SS3Flag);
234 charOff++;
235 DesignatorLength = 3;
236 break;
237 default:
238 DesignatorLength = 0;
239 }
240 }
241 }
242 }
243 if (remainIndex > DesignatorLength) {
244 for(i = 0; i < remainIndex-DesignatorLength; i++)
245 remainByte[i] = remainByte[DesignatorLength+1+i];
246 remainIndex = i-1;
247 } else {
248 remainIndex = -1;
249 }
250 break;
251 default:
252 if (!shiftout) {
253 output[charOff] = (char)remainByte[0];
254 charOff++;
255 } else {
256 switch (state) {
257 case G0:
258 firstByte = remainByte[0];
259 state = G1;
260 break;
261 case G1:
262 output[charOff] = getUnicode(firstByte, remainByte[0],
263 SOFlag);
264 charOff++;
265 state = G0;
266 break;
267 }
268 }
269 if (remainIndex > 0)
270 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
271 remainIndex--;
272 }
273 }
274 return charOff - outOff;
275 }
276}