001: /*
002: * Copyright 1997 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: package sun.io;
026:
027: public abstract class CharToByteDBCS_ASCII extends CharToByteConverter {
028:
029: private char highHalfZoneCode;
030: private byte[] outputByte = new byte[2];
031:
032: protected short index1[];
033: protected String index2;
034: protected String index2a;
035: protected int mask1;
036: protected int mask2;
037: protected int shift;
038:
039: /**
040: * flush out any residual data and reset the buffer state
041: */
042: public int flush(byte[] output, int outStart, int outEnd)
043: throws MalformedInputException,
044: ConversionBufferFullException {
045:
046: if (highHalfZoneCode != 0) {
047: reset();
048: badInputLength = 0;
049: throw new MalformedInputException();
050: }
051:
052: reset();
053: return 0;
054: }
055:
056: /**
057: * Character conversion
058: */
059: public int convert(char[] input, int inOff, int inEnd,
060: byte[] output, int outOff, int outEnd)
061: throws UnknownCharacterException, MalformedInputException,
062: ConversionBufferFullException {
063: char inputChar;
064: int inputSize;
065:
066: byteOff = outOff;
067: charOff = inOff;
068:
069: while (charOff < inEnd) {
070:
071: int index;
072: int theBytes;
073: int spaceNeeded;
074:
075: if (highHalfZoneCode == 0) {
076: inputChar = input[charOff];
077: inputSize = 1;
078: } else {
079: inputChar = highHalfZoneCode;
080: inputSize = 0;
081: highHalfZoneCode = 0;
082: }
083:
084: // Is this a high surrogate?
085: if (inputChar >= '\ud800' && inputChar <= '\udbff') {
086: // Is this the last character of the input?
087: if (charOff + inputSize >= inEnd) {
088: highHalfZoneCode = inputChar;
089: charOff += inputSize;
090: break;
091: }
092:
093: // Is there a low surrogate following?
094: inputChar = input[charOff + inputSize];
095: if (inputChar >= '\udc00' && inputChar <= '\udfff') {
096:
097: // We have a valid surrogate pair. Too bad we don't do
098: // surrogates. Is substitution enabled?
099: if (subMode) {
100: if (subBytes.length == 1) {
101: outputByte[0] = 0x00;
102: outputByte[1] = subBytes[0];
103: } else {
104: outputByte[0] = subBytes[0];
105: outputByte[1] = subBytes[1];
106: }
107:
108: inputSize++;
109: } else {
110: badInputLength = 2;
111: throw new UnknownCharacterException();
112: }
113: } else {
114:
115: // We have a malformed surrogate pair
116: badInputLength = 1;
117: throw new MalformedInputException();
118: }
119: }
120:
121: // Is this an unaccompanied low surrogate?
122: else if (inputChar >= '\uDC00' && inputChar <= '\uDFFF') {
123: badInputLength = 1;
124: throw new MalformedInputException();
125: } else {
126:
127: // We have a valid character, get the bytes for it
128: index = index1[((inputChar & mask1) >> shift)]
129: + (inputChar & mask2);
130: if (index < 15000)
131: theBytes = (int) (index2.charAt(index));
132: else
133: theBytes = (int) (index2a.charAt(index - 15000));
134: outputByte[0] = (byte) ((theBytes & 0x0000ff00) >> 8);
135: outputByte[1] = (byte) (theBytes & 0x000000ff);
136: }
137:
138: // if there was no mapping - look for substitution characters
139: if (outputByte[0] == 0x00 && outputByte[1] == 0x00
140: && inputChar != '\u0000') {
141: if (subMode) {
142: if (subBytes.length == 1) {
143: outputByte[0] = 0x00;
144: outputByte[1] = subBytes[0];
145: } else {
146: outputByte[0] = subBytes[0];
147: outputByte[1] = subBytes[1];
148: }
149: } else {
150: badInputLength = 1;
151: throw new UnknownCharacterException();
152: }
153: }
154:
155: if (outputByte[0] == 0x00)
156: spaceNeeded = 1;
157: else
158: spaceNeeded = 2;
159:
160: if (byteOff + spaceNeeded > outEnd)
161: throw new ConversionBufferFullException();
162:
163: if (spaceNeeded == 1)
164: output[byteOff++] = outputByte[1];
165: else {
166: output[byteOff++] = outputByte[0];
167: output[byteOff++] = outputByte[1];
168: }
169:
170: charOff += inputSize;
171: }
172:
173: return byteOff - outOff;
174: }
175:
176: /**
177: * Resets converter to its initial state.
178: */
179: public void reset() {
180: charOff = byteOff = 0;
181: highHalfZoneCode = 0;
182: }
183:
184: /**
185: * Returns the maximum number of bytes needed to convert a char.
186: */
187: public int getMaxBytesPerChar() {
188: return 2;
189: }
190:
191: /**
192: * Returns true if the given character can be converted to the
193: * target character encoding.
194: */
195: public boolean canConvert(char ch) {
196: int index;
197: int theBytes;
198:
199: index = index1[((ch & mask1) >> shift)] + (ch & mask2);
200: if (index < 15000)
201: theBytes = (int) (index2.charAt(index));
202: else
203: theBytes = (int) (index2a.charAt(index - 15000));
204:
205: if (theBytes != 0)
206: return (true);
207:
208: // only return true if input char was unicode null - all others are
209: // undefined
210: return (ch == '\u0000');
211:
212: }
213:
214: }
|