blob: 76ae1411a4742ea6318e0b66c0f6caf530c49004 [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 * @author Tom Zhou
30 */
31public class ByteToCharISO2022CN extends ByteToCharConverter
32{
33 private String SODesignator[];
34 private String SS2Designator[] = null;
35 private String SS3Designator[] = null;
36 private ByteToCharConverter SOConverter[];
37 private ByteToCharConverter SS2Converter[] = null;
38 private ByteToCharConverter SS3Converter[] = null;
39
40 private static final byte ISO_ESC = 0x1b;
41 private static final byte ISO_SI = 0x0f;
42 private static final byte ISO_SO = 0x0e;
43 private static final byte ISO_SS2_7 = 0x4e;
44 private static final byte ISO_SS3_7 = 0x4f;
45 private static final byte MSB = (byte)0x80;
46 private static final char REPLACE_CHAR = '\uFFFD';
47 private static final byte maximumDesignatorLength = 3;
48
49 private static final byte SOFlag = 0;
50 private static final byte SS2Flag = 1;
51 private static final byte SS3Flag = 2;
52 private static final byte G0 = 0;
53 private static final byte G1 = 1;
54
55 private ByteToCharConverter tmpConverter[];
56
57 private int curSODes, curSS2Des, curSS3Des;
58 private boolean shiftout;
59
60 private byte remainByte[] = new byte[10];
61 private int remainIndex = -1;
62 private byte state, firstByte;
63
64 public void reset()
65 {
66 int i = 0;
67
68 shiftout = false;
69 state = G0;
70 firstByte = 0;
71
72 curSODes = 0;
73 curSS2Des = 0;
74 curSS3Des = 0;
75
76 charOff = byteOff = 0;
77 remainIndex = -1;
78
79 for(i = 0; i < remainByte.length; i++)
80 remainByte[i] = 0;
81 }
82
83 public int flush(char[] output, int outStart, int outEnd)
84 throws MalformedInputException
85 {
86 int i;
87 if (state != G0) {
88 badInputLength = 0;
89 throw new MalformedInputException();
90 }
91 reset();
92 return 0;
93 }
94
95 private byte[] savetyGetSrc(byte[] input, int inOff, int inEnd, int nbytes)
96 {
97 int i;
98 byte tmp[];
99
100 if(inOff <= (inEnd-nbytes+1))
101 tmp = new byte[nbytes];
102 else
103 tmp = new byte[inEnd-inOff];
104
105 for(i = 0; i < tmp.length; i++)
106 tmp[i] = input[inOff+i];
107 return tmp;
108 }
109
110 private char getUnicode(byte byte1, byte byte2, byte shiftFlag)
111 {
112 byte1 |= MSB;
113 byte2 |= MSB;
114 char[] tmpChar = new char[1];
115
116 switch(shiftFlag) {
117 case SOFlag:
118 try {
119 byte[] tmpByte = {byte1,byte2};
120 SOConverter[curSODes].convert(tmpByte, 0, 2, tmpChar, 0, 1);
121 }
122 catch (Exception e) {}
123 break;
124 case SS2Flag:
125 try {
126 byte[] tmpByte = {(byte)0x8e, (byte)0xa2, byte1, byte2};
127 SS2Converter[curSS2Des].convert(tmpByte, 0, 4, tmpChar, 0, 1);
128 }
129 catch (Exception e){}
130 break;
131 case SS3Flag:
132 try {
133 byte[] tmpByte = {(byte)0x8e, (byte)0xa3, byte1,byte2};
134 SS3Converter[curSS3Des].convert(tmpByte, 0, 4, tmpChar, 0, 1);
135 }
136 catch (Exception e){}
137 break;
138 default:
139 tmpChar[0] = REPLACE_CHAR;
140 }
141 return tmpChar[0];
142 }
143
144 public final int convert(byte[] input, int inOff, int inEnd,
145 char[] output, int outOff, int outEnd)
146 throws ConversionBufferFullException,
147 MalformedInputException
148 {
149 int i;
150 int DesignatorLength = 0;
151 charOff = outOff;
152 byteOff = inOff;
153
154 // Loop until we hit the end of the input
155 while (byteOff < inEnd) {
156 // If we don't have room for the output, throw an exception
157 if (charOff >= outEnd)
158 throw new ConversionBufferFullException();
159 if(remainIndex < 0) {
160 remainByte[0] = input[byteOff];
161 remainIndex = 0;
162 byteOff++;
163 }
164 switch (remainByte[0]) {
165 case ISO_SO:
166 shiftout = true;
167 if(remainIndex > 0)
168 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
169 remainIndex--;
170 break;
171 case ISO_SI:
172 shiftout = false;
173 if(remainIndex > 0)
174 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
175 remainIndex--;
176 break;
177 case ISO_ESC:
178 byte tmp[] = savetyGetSrc(input, byteOff, inEnd,
179 (maximumDesignatorLength-remainIndex));
180 System.arraycopy(tmp, 0, remainByte, remainIndex+1, tmp.length);
181
182 remainIndex += tmp.length;
183 byteOff += tmp.length;
184 if(tmp.length<(maximumDesignatorLength-remainIndex))
185 break;
186 String tmpString = new String(remainByte, 1, remainIndex);
187 for (i = 0; i < SODesignator.length; i++) {
188 if(tmpString.indexOf(SODesignator[i]) == 0) {
189 curSODes = i;
190 DesignatorLength = SODesignator[i].length();
191 break;
192 }
193 }
194
195 if (DesignatorLength == 0) { // designator not recognized
196 badInputLength = tmp.length;
197 throw new MalformedInputException();
198 }
199
200 if (i == SODesignator.length) {
201 for (i = 0; i < SS2Designator.length; i++) {
202 if(tmpString.indexOf(SS2Designator[i]) == 0) {
203 curSS2Des = i;
204 DesignatorLength = SS2Designator[i].length();
205 break;
206 }
207 }
208 if(i == SS2Designator.length) {
209 for(i = 0; i < SS3Designator.length; i++) {
210 if (tmpString.indexOf(SS3Designator[i]) == 0) {
211 curSS3Des = i;
212 DesignatorLength = SS3Designator[i].length();
213 break;
214 }
215 }
216 if (i == SS3Designator.length) {
217 switch(remainByte[1]) {
218 case ISO_SS2_7:
219 output[charOff] = getUnicode(remainByte[2],
220 remainByte[3],
221 SS2Flag);
222 charOff++;
223 DesignatorLength = 3;
224 break;
225 case ISO_SS3_7:
226 output[charOff] = getUnicode(remainByte[2],
227 remainByte[3],
228 SS3Flag);
229 charOff++;
230 DesignatorLength = 3;
231 break;
232 default:
233 DesignatorLength = 0;
234 }
235 }
236 }
237 }
238 if (remainIndex > DesignatorLength) {
239 for(i = 0; i < remainIndex-DesignatorLength; i++)
240 remainByte[i] = remainByte[DesignatorLength+1+i];
241 remainIndex = i-1;
242 } else {
243 remainIndex = -1;
244 }
245 break;
246 default:
247 if (!shiftout) {
248 output[charOff] = (char)remainByte[0];
249 charOff++;
250 } else {
251 switch (state) {
252 case G0:
253 firstByte = remainByte[0];
254 state = G1;
255 break;
256 case G1:
257 output[charOff] = getUnicode(firstByte, remainByte[0],
258 SOFlag);
259 charOff++;
260 state = G0;
261 break;
262 }
263 }
264 if (remainIndex > 0)
265 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex);
266 remainIndex--;
267 }
268 }
269 return charOff - outOff;
270 }
271
272 public ByteToCharISO2022CN()
273 {
274 SODesignator = new String[3];
275 SODesignator[0] = "$A";
276 SODesignator[1] = "$)A";
277 SODesignator[2] = "$)G";
278 SS2Designator = new String[1];
279 SS2Designator[0] = "$*H";
280 SS3Designator = new String[1];
281 SS3Designator[0] = "$+I";
282
283 SOConverter = new ByteToCharConverter[3];
284 SS2Converter = new ByteToCharConverter[1];
285 SS3Converter = new ByteToCharConverter[1];
286
287 try {
288 SOConverter[0] = SOConverter[1]
289 = ByteToCharConverter.getConverter("GB2312");
290 SOConverter[2] = SS2Converter[0] = SS3Converter[0]
291 = ByteToCharConverter.getConverter("CNS11643");
292 } catch (Exception e) {};
293 }
294
295 // Return the character set id
296 public String getCharacterEncoding()
297 {
298 return "ISO2022CN";
299 }
300}