001: /*
002: * @(#)ByteToCharDBCS_EBCDIC.java 1.10 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: package sun.io;
028:
029: public abstract class ByteToCharDBCS_EBCDIC extends ByteToCharConverter {
030: private static final int SBCS = 0;
031: private static final int DBCS = 1;
032: private static final int SO = 0x0e;
033: private static final int SI = 0x0f;
034: private int currentState;
035: private boolean savedBytePresent;
036: private byte savedByte;
037: protected String singleByteToChar;
038: protected short index1[];
039: protected String index2;
040: protected int mask1;
041: protected int mask2;
042: protected int shift;
043:
044: public ByteToCharDBCS_EBCDIC() {
045: super ();
046: currentState = SBCS;
047: savedBytePresent = false;
048: }
049:
050: public int flush(char[] output, int outStart, int outEnd)
051: throws MalformedInputException {
052: if (savedBytePresent) {
053: reset();
054: badInputLength = 0;
055: throw new MalformedInputException();
056: }
057: reset();
058: return 0;
059: }
060:
061: /**
062: * Character conversion
063: */
064: public int convert(byte[] input, int inOff, int inEnd,
065: char[] output, int outOff, int outEnd)
066: throws UnknownCharacterException, MalformedInputException,
067: ConversionBufferFullException {
068: int inputSize;
069: char outputChar = '\uFFFD';
070: charOff = outOff;
071: byteOff = inOff;
072: while (byteOff < inEnd) {
073: int byte1, byte2;
074: int v;
075: if (!savedBytePresent) {
076: byte1 = input[byteOff];
077: inputSize = 1;
078: } else {
079: byte1 = savedByte;
080: savedBytePresent = false;
081: inputSize = 0;
082: }
083: if (byte1 == SO) {
084: // For SO characters - simply validate the state and if OK
085: // update the state and go to the next byte
086:
087: if (currentState != SBCS) {
088: badInputLength = 1;
089: throw new MalformedInputException();
090: } else {
091: currentState = DBCS;
092: byteOff += inputSize;
093: }
094: } else if (byte1 == SI) {
095: // For SI characters - simply validate the state and if OK
096: // update the state and go to the next byte
097:
098: if (currentState != DBCS) {
099: badInputLength = 1;
100: throw new MalformedInputException();
101: } else {
102: currentState = SBCS;
103: byteOff += inputSize;
104: }
105: } else {
106: // Process the real data characters
107:
108: if (byte1 < 0)
109: byte1 += 256;
110: if (currentState == SBCS) {
111: outputChar = singleByteToChar.charAt(byte1);
112: } else {
113: // for a DBCS character - architecture dictates the
114: // valid range of 1st bytes
115:
116: if (byte1 < 0x40 || byte1 > 0xfe) {
117: badInputLength = 1;
118: throw new MalformedInputException();
119: }
120: if (byteOff + inputSize >= inEnd) {
121: // We have been split in the middle if a character
122: // save the first byte for next time around
123:
124: savedByte = (byte) byte1;
125: savedBytePresent = true;
126: byteOff += inputSize;
127: break;
128: }
129: byte2 = input[byteOff + inputSize];
130: if (byte2 < 0)
131: byte2 += 256;
132: inputSize++;
133: // validate the pair of bytes meet the architecture
134:
135: if ((byte1 != 0x40 || byte2 != 0x40)
136: && (byte2 < 0x41 || byte2 > 0xfe)) {
137: badInputLength = 2;
138: throw new MalformedInputException();
139: }
140: // Lookup in the two level index
141: v = byte1 * 256 + byte2;
142: outputChar = index2
143: .charAt(index1[((v & mask1) >> shift)]
144: + (v & mask2));
145: }
146: if (outputChar == '\uFFFD') {
147: if (subMode)
148: outputChar = subChars[0];
149: else {
150: badInputLength = inputSize;
151: throw new UnknownCharacterException();
152: }
153: }
154: if (charOff >= outEnd)
155: throw new ConversionBufferFullException();
156: output[charOff++] = outputChar;
157: byteOff += inputSize;
158: }
159: }
160: return charOff - outOff;
161: }
162:
163: /**
164: * Resets the converter.
165: */
166: public void reset() {
167: charOff = byteOff = 0;
168: currentState = SBCS;
169: savedBytePresent = false;
170: }
171: }
|