001: /*
002: * @(#)ByteToCharDoubleByte.java 1.12 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: * @author Limin Shi
032: * Sean Jiang
033: */
034:
035: public abstract class ByteToCharDoubleByte extends ByteToCharConverter {
036: protected byte savedByte;
037: /*
038: * 1st level index, provided by subclass
039: */
040: protected short index1[];
041: /*
042: * 2nd level index, provided by subclass
043: * every string has 0x10*(end-start+1) characters.
044: */
045: protected String index2[];
046: protected int start;
047: protected int end;
048: /*
049: * Size of bad input that caused conversion to stop
050: */
051: protected int badInputLength;
052:
053: public ByteToCharDoubleByte() {
054: super ();
055: savedByte = 0;
056: }
057:
058: public int flush(char[] output, int outStart, int outEnd)
059: throws MalformedInputException {
060: if (savedByte != 0) {
061: reset();
062: badInputLength = 0;
063: throw new MalformedInputException();
064: }
065: reset();
066: return 0;
067: }
068:
069: /**
070: * Converts sequences of bytes to characters.
071: * Conversions that result in Exceptions can be restarted by calling
072: * convert again, with appropriately modified parameters.
073: * @return the characters written to output.
074: * @param input byte array containing text in Double/single Byte
075: * @param inStart offset in input array
076: * @param inEnd offset of last byte to be converted
077: * @param output character array to receive conversion result
078: * @param outStart starting offset
079: * @param outEnd offset of last byte to be written to
080: * @throw UnsupportedCharacterException for any bytes
081: * that cannot be converted to the external character set.
082: */
083: public int convert(byte[] input, int inOff, int inEnd,
084: char[] output, int outOff, int outEnd)
085: throws UnknownCharacterException, MalformedInputException,
086: ConversionBufferFullException {
087: char outputChar = REPLACE_CHAR;
088: int inputSize = 0; // Size of input
089: // Record beginning offsets
090: charOff = outOff;
091: byteOff = inOff;
092: // Loop until we hit the end of the input
093: while (byteOff < inEnd) {
094: int byte1, byte2;
095: if (savedByte == 0) {
096: byte1 = input[byteOff];
097: inputSize = 1;
098: } else {
099: byte1 = savedByte;
100: savedByte = 0;
101: inputSize = 0;
102: }
103: outputChar = convSingleByte(byte1);
104: if (outputChar == REPLACE_CHAR) { // DoubleByte char
105: if (byteOff + inputSize >= inEnd) {
106: // split in the middle of a character
107: // save the first byte for next time around
108: savedByte = (byte) byte1;
109: byteOff += inputSize;
110: break;
111: }
112: byte1 &= 0xff;
113: byte2 = input[byteOff + inputSize] & 0xff;
114: inputSize++;
115: outputChar = getUnicode(byte1, byte2);
116: }
117: if (outputChar == REPLACE_CHAR) {
118: if (subMode)
119: outputChar = subChars[0];
120: else {
121: badInputLength = inputSize;
122: throw new UnknownCharacterException();
123: }
124: }
125: if (charOff >= outEnd)
126: throw new ConversionBufferFullException();
127: output[charOff++] = outputChar;
128: byteOff += inputSize;
129: }
130: return charOff - outOff;
131: }
132:
133: /**
134: * Resets the converter.
135: * Call this method to reset the converter to its initial state
136: */
137: public void reset() {
138: byteOff = charOff = 0;
139: savedByte = 0;
140: }
141:
142: /*
143: * Can be changed by subclass
144: */
145: protected char convSingleByte(int b) {
146: if (b >= 0)
147: return (char) b;
148: return REPLACE_CHAR;
149: }
150:
151: /*
152: * Can be changed by subclass
153: */
154: protected char getUnicode(int byte1, int byte2) {
155: if ((byte2 < start) || (byte2 > end))
156: return REPLACE_CHAR;
157: int n = (index1[byte1] & 0xf) * (end - start + 1)
158: + (byte2 - start);
159: return index2[index1[byte1] >> 4].charAt(n);
160: }
161:
162: protected final static char REPLACE_CHAR = '\uFFFD';
163: }
|