001: /*
002: * @(#)CharToByteDBCS_ASCII.java 1.11 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 CharToByteDBCS_ASCII extends CharToByteConverter {
030: private char highHalfZoneCode;
031: private byte[] outputByte = new byte[2];
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: if (highHalfZoneCode != 0) {
046: reset();
047: badInputLength = 0;
048: throw new MalformedInputException();
049: }
050: reset();
051: return 0;
052: }
053:
054: /**
055: * Character conversion
056: */
057: public int convert(char[] input, int inOff, int inEnd,
058: byte[] output, int outOff, int outEnd)
059: throws UnknownCharacterException, MalformedInputException,
060: ConversionBufferFullException {
061: char inputChar;
062: int inputSize;
063: byteOff = outOff;
064: charOff = inOff;
065: while (charOff < inEnd) {
066: int index;
067: int theBytes;
068: int spaceNeeded;
069: if (highHalfZoneCode == 0) {
070: inputChar = input[charOff];
071: inputSize = 1;
072: } else {
073: inputChar = highHalfZoneCode;
074: inputSize = 0;
075: highHalfZoneCode = 0;
076: }
077: // Is this a high surrogate?
078: if (inputChar >= '\ud800' && inputChar <= '\udbff') {
079: // Is this the last character of the input?
080: if (charOff + inputSize >= inEnd) {
081: highHalfZoneCode = inputChar;
082: charOff += inputSize;
083: break;
084: }
085: // Is there a low surrogate following?
086: inputChar = input[charOff + inputSize];
087: if (inputChar >= '\udc00' && inputChar <= '\udfff') {
088: // We have a valid surrogate pair. Too bad we don't do
089: // surrogates. Is substitution enabled?
090: if (subMode) {
091: if (subBytes.length == 1) {
092: outputByte[0] = 0x00;
093: outputByte[1] = subBytes[0];
094: } else {
095: outputByte[0] = subBytes[0];
096: outputByte[1] = subBytes[1];
097: }
098: inputSize++;
099: } else {
100: badInputLength = 2;
101: throw new UnknownCharacterException();
102: }
103: } else {
104: // We have a malformed surrogate pair
105: badInputLength = 1;
106: throw new MalformedInputException();
107: }
108: } // Is this an unaccompanied low surrogate?
109: else if (inputChar >= '\uDC00' && inputChar <= '\uDFFF') {
110: badInputLength = 1;
111: throw new MalformedInputException();
112: } else {
113: // We have a valid character, get the bytes for it
114: index = index1[((inputChar & mask1) >> shift)]
115: + (inputChar & mask2);
116: if (index < 15000)
117: theBytes = (int) (index2.charAt(index));
118: else
119: theBytes = (int) (index2a.charAt(index - 15000));
120: outputByte[0] = (byte) ((theBytes & 0x0000ff00) >> 8);
121: outputByte[1] = (byte) (theBytes & 0x000000ff);
122: }
123: // if there was no mapping - look for substitution characters
124: if (outputByte[0] == 0x00 && outputByte[1] == 0x00
125: && inputChar != '\u0000') {
126: if (subMode) {
127: if (subBytes.length == 1) {
128: outputByte[0] = 0x00;
129: outputByte[1] = subBytes[0];
130: } else {
131: outputByte[0] = subBytes[0];
132: outputByte[1] = subBytes[1];
133: }
134: } else {
135: badInputLength = 1;
136: throw new UnknownCharacterException();
137: }
138: }
139: if (outputByte[0] == 0x00)
140: spaceNeeded = 1;
141: else
142: spaceNeeded = 2;
143: if (byteOff + spaceNeeded > outEnd)
144: throw new ConversionBufferFullException();
145: if (spaceNeeded == 1)
146: output[byteOff++] = outputByte[1];
147: else {
148: output[byteOff++] = outputByte[0];
149: output[byteOff++] = outputByte[1];
150: }
151: charOff += inputSize;
152: }
153: return byteOff - outOff;
154: }
155:
156: /**
157: * Resets converter to its initial state.
158: */
159: public void reset() {
160: charOff = byteOff = 0;
161: highHalfZoneCode = 0;
162: }
163:
164: /**
165: * Returns the maximum number of bytes needed to convert a char.
166: */
167: public int getMaxBytesPerChar() {
168: return 2;
169: }
170:
171: /**
172: * Returns true if the given character can be converted to the
173: * target character encoding.
174: */
175: public boolean canConvert(char ch) {
176: int index;
177: int theBytes;
178: index = index1[((ch & mask1) >> shift)] + (ch & mask2);
179: if (index < 15000)
180: theBytes = (int) (index2.charAt(index));
181: else
182: theBytes = (int) (index2a.charAt(index - 15000));
183: if (theBytes != 0)
184: return (true);
185: // only return true if input char was unicode null - all others are
186: // undefined
187: return (ch == '\u0000');
188: }
189: }
|