001: /*
002: * @(#)ByteToCharISO2022JP.java 1.23 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: public class ByteToCharISO2022JP extends ByteToCharJIS0208 {
031: private static final int ASCII = 0; // ESC ( B
032: private static final int JISX0201_1976 = 1; // ESC ( J
033: private static final int JISX0208_1978 = 2; // ESC $ @
034: private static final int JISX0208_1983 = 3; // ESC $ B
035: private static final int JISX0201_1976_KANA = 4; // ESC ( I
036: private static final int SHIFTOUT = 5; // SO (0x0e)
037: private int currentState;
038: private int savedSize;
039: private byte[] savedBytes;
040:
041: public ByteToCharISO2022JP() {
042: super ();
043: savedBytes = new byte[2];
044: currentState = ASCII;
045: savedSize = 0;
046: }
047:
048: public int flush(char[] output, int outStart, int outEnd)
049: throws MalformedInputException {
050: if (savedSize != 0) {
051: savedSize = 0;
052: currentState = ASCII;
053: badInputLength = 0;
054: throw new MalformedInputException();
055: }
056: byteOff = charOff = 0;
057: return 0;
058: }
059:
060: /**
061: * Character conversion
062: */
063: public int convert(byte[] input, int inOff, int inEnd,
064: char[] output, int outOff, int outEnd)
065: throws UnknownCharacterException, MalformedInputException,
066: ConversionBufferFullException {
067: int previousState = ASCII;
068: int inputSize = 0;
069: char outputChar = '\uFFFD';
070: // readOff keeps the actual buffer's pointer.
071: // byteOff keeps original buffer's pointer.
072: int readOff = byteOff = inOff;
073: if (savedSize != 0) {
074: if (savedBytes[0] == 0x1b) { // ESC
075: if ((savedSize == 2
076: && (savedBytes[1] == 0x28 && input[0] != 'B'
077: && input[0] != 'J' && input[0] != 'I') && (savedBytes[1] == 0x24
078: && input[0] != '@' && input[0] != 'B'))
079: || ((savedSize == 1) && (input[0] != 0x28 && input[0] != 0x24))) {
080: badInputLength = 0;
081: throw new MalformedInputException();
082: }
083: if ((inEnd - inOff) == 1 && savedSize == 1
084: && savedBytes[0] == 0x1b) {
085: savedSize = 2;
086: savedBytes[1] = input[0];
087: byteOff++;
088: return 0;
089: }
090: }
091: byte[] newBuf = new byte[inEnd - inOff + savedSize];
092: for (int i = 0; i < savedSize; i++) {
093: newBuf[i] = savedBytes[i];
094: }
095: System.arraycopy(input, inOff, newBuf, savedSize, inEnd
096: - inOff);
097: byteOff -= savedSize;
098: input = newBuf;
099: inOff = 0;
100: inEnd = newBuf.length;
101: savedSize = 0;
102: }
103: charOff = outOff;
104: readOff = inOff;
105: while (readOff < inEnd) {
106: int byte1, byte2, byte3;
107: boolean noOutput = false;
108: // Is there room in the output buffer for the result?
109: if (charOff >= outEnd) {
110: throw new ConversionBufferFullException();
111: }
112: // Get the input byte
113: byte1 = input[readOff] & 0xFF;
114: inputSize = 1;
115: if ((byte1 & (byte) 0x80) != 0) {
116: badInputLength = 1;
117: throw new MalformedInputException();
118: }
119: // Is this a escape sequence?
120: while (byte1 == 0x1b || byte1 == 0x0e || byte1 == 0x0f) {
121: if (byte1 == 0x1b) { // ESC
122: if (readOff + inputSize + 1 >= inEnd) {
123: if (readOff + inputSize >= inEnd) {
124: savedSize = 1;
125: savedBytes[0] = (byte) byte1;
126: } else {
127: savedSize = 2;
128: savedBytes[0] = (byte) byte1;
129: savedBytes[1] = (byte) input[readOff
130: + inputSize];
131: inputSize++;
132: }
133: break;
134: }
135: byte2 = input[readOff + inputSize] & 0xFF;
136: inputSize++;
137: if ((byte2 & (byte) 0x80) != 0) {
138: badInputLength = 2;
139: throw new MalformedInputException();
140: }
141: if (byte2 == 0x28) {
142: byte3 = input[readOff + inputSize] & 0xFF;
143: inputSize++;
144: if (byte3 == 'B') {
145: currentState = ASCII;
146: } else if (byte3 == 'J') {
147: currentState = JISX0201_1976;
148: } else if (byte3 == 'I') {
149: currentState = JISX0201_1976_KANA;
150: } else {
151: // illegal ESC sequence
152: badInputLength = 3;
153: throw new MalformedInputException();
154: }
155: } else if (byte2 == '$') {
156: byte3 = input[readOff + inputSize] & 0xFF;
157: inputSize++;
158: if ((byte3 & (byte) 0x80) != 0) {
159: badInputLength = 3;
160: throw new MalformedInputException();
161: }
162: if (byte3 == '@') {
163: currentState = JISX0208_1978;
164: } else if (byte3 == 'B') {
165: currentState = JISX0208_1983;
166: } else {
167: // illegal ESC sequence
168: badInputLength = 3;
169: throw new MalformedInputException();
170: }
171: } else {
172: // illegal ESC sequence
173: badInputLength = 2;
174: throw new MalformedInputException();
175: }
176: if (readOff + inputSize >= inEnd) {
177: noOutput = true;
178: break;
179: } else {
180: byte1 = input[readOff + inputSize];
181: inputSize++;
182: }
183: } else if (byte1 == 0x0e) { // shift out for one byte kana
184: previousState = currentState;
185: currentState = SHIFTOUT;
186: if (readOff + inputSize >= inEnd) {
187: noOutput = true;
188: break;
189: }
190: byte1 = input[readOff + inputSize];
191: inputSize++;
192: if ((byte1 & (byte) 0x80) != 0) {
193: badInputLength = 1;
194: throw new MalformedInputException();
195: }
196: } else if (byte1 == 0x0f) { // shift in for previous mode
197: currentState = previousState;
198: if (readOff + inputSize >= inEnd) {
199: noOutput = true;
200: break;
201: }
202: byte1 = input[readOff + inputSize];
203: inputSize++;
204: if ((byte1 & (byte) 0x80) != 0) {
205: badInputLength = 1;
206: throw new MalformedInputException();
207: }
208: }
209: }
210: if (noOutput || savedSize != 0) {
211: byteOff += inputSize;
212: break;
213: }
214: noOutput = false;
215: switch (currentState) {
216: case ASCII:
217: outputChar = (char) (byte1 & 0xff);
218: break;
219:
220: case JISX0201_1976:
221: switch (byte1) {
222: case 0x5c:
223: outputChar = '\u00a5';
224: break;
225:
226: case 0x7e:
227: outputChar = '\u203e';
228: break;
229:
230: default:
231: outputChar = (char) byte1;
232: break;
233: }
234: break;
235:
236: case JISX0208_1978:
237: case JISX0208_1983:
238: if (readOff + inputSize >= inEnd) {
239: savedSize = 1;
240: savedBytes[0] = (byte) byte1;
241: break;
242: }
243: byte2 = input[readOff + inputSize] & 0xff;
244: inputSize++;
245: if ((byte2 & (byte) 0x80) != 0) {
246: badInputLength = 1;
247: throw new MalformedInputException();
248: }
249: // jisx0208Chars table convert FULLWIDTH_REVERSE_SOLIDUS
250: // 0x2140 to REVERSE_SOLIDUS (BACKSLASH) 0x5c.
251: // This behavior causes problem because
252: // 0x5c is special escape character for java.
253: if (byte1 == 0x21 && byte2 == 0x40) {
254: outputChar = '\uFF3C';
255: } else {
256: try {
257: outputChar = getUnicode(byte1, byte2);
258: } catch (ArrayIndexOutOfBoundsException e) {
259: outputChar = '\uFFFD';
260: }
261: }
262: break;
263:
264: case JISX0201_1976_KANA:
265: case SHIFTOUT:
266: if (byte1 > 0x60) {
267: badInputLength = 1;
268: throw new MalformedInputException();
269: }
270: outputChar = (char) (byte1 + 0xff40);
271: break;
272: }
273: if (savedSize != 0) {
274: byteOff += inputSize;
275: break;
276: }
277: if (outputChar == '\uFFFD') {
278: if (subMode)
279: outputChar = subChars[0];
280: else {
281: badInputLength = inputSize;
282: throw new UnknownCharacterException();
283: }
284: }
285: readOff += inputSize;
286: byteOff += inputSize;
287: output[charOff++] = outputChar;
288: }
289: return charOff - outOff;
290: }
291:
292: public void reset() {
293: byteOff = charOff = 0;
294: currentState = ASCII;
295: savedSize = 0;
296: }
297:
298: public String getCharacterEncoding() {
299: return "ISO2022JP";
300: }
301: }
|