1 /* 2 * Copyright 1997 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 package sun.io; 26 27 import sun.nio.cs.Surrogate; 28 import sun.nio.cs.ext.DoubleByte; 29 import static sun.nio.cs.CharsetMapping.*; 30 31 public abstract class CharToByteDBCS_ASCII extends CharToByteConverter 32 { 33 34 private char highHalfZoneCode; 35 private byte[] outputByte = new byte[2]; 36 37 private DoubleByte.Encoder enc; 38 39 public CharToByteDBCS_ASCII(DoubleByte.Encoder enc) { 40 super(); 41 this.enc = enc; 42 } 43 44 int encodeChar(char c) { 45 return enc.encodeChar(c); 46 } 47 48 /** 49 * flush out any residual data and reset the buffer state 50 */ 51 public int flush(byte [] output, int outStart, int outEnd) 52 throws MalformedInputException, ConversionBufferFullException 53 { 54 55 if (highHalfZoneCode != 0) { 56 reset(); 57 badInputLength = 0; 58 throw new MalformedInputException(); 59 } 60 61 reset(); 62 return 0; 63 } 64 65 /** 66 * Character conversion 67 */ 68 public int convert(char[] input, int inOff, int inEnd, 69 byte[] output, int outOff, int outEnd) 70 throws UnknownCharacterException, MalformedInputException, 71 ConversionBufferFullException 72 { 73 char inputChar; 74 int inputSize; 75 76 byteOff = outOff; 77 charOff = inOff; 78 79 while(charOff < inEnd) { 80 int index; 81 int theBytes; 82 int spaceNeeded; 83 84 if (highHalfZoneCode == 0) { 85 inputChar = input[charOff]; 86 inputSize = 1; 87 } else { 88 inputChar = highHalfZoneCode; 89 inputSize = 0; 90 highHalfZoneCode = 0; 91 } 92 93 // Is this a high surrogate? 94 if (Surrogate.isHigh(inputChar)) { 95 // Is this the last character of the input? 96 if (charOff + inputSize >= inEnd) { 97 highHalfZoneCode = inputChar; 98 charOff += inputSize; 99 break; 100 } 101 102 // Is there a low surrogate following? 103 inputChar = input[charOff + inputSize]; 104 if (Surrogate.isLow(inputChar)) { 105 // We have a valid surrogate pair. Too bad we don't do 106 // surrogates. Is substitution enabled? 107 if (subMode) { 108 if (subBytes.length == 1) { 109 outputByte[0] = 0x00; 110 outputByte[1] = subBytes[0]; 111 } 112 else { 113 outputByte[0] = subBytes[0]; 114 outputByte[1] = subBytes[1]; 115 } 116 inputSize++; 117 } else { 118 badInputLength = 2; 119 throw new UnknownCharacterException(); 120 } 121 } else { 122 // We have a malformed surrogate pair 123 badInputLength = 1; 124 throw new MalformedInputException(); 125 } 126 } 127 // Is this an unaccompanied low surrogate? 128 else if (Surrogate.isLow(inputChar)) { 129 badInputLength = 1; 130 throw new MalformedInputException(); 131 } else { 132 133 // We have a valid character, get the bytes for it 134 theBytes = encodeChar(inputChar); 135 if (theBytes == UNMAPPABLE_ENCODING) { 136 // if there was no mapping - look for substitution characters 137 if (subMode) { 138 if (subBytes.length == 1) { 139 outputByte[0] = 0x00; 140 outputByte[1] = subBytes[0]; 141 } else { 142 outputByte[0] = subBytes[0]; 143 outputByte[1] = subBytes[1]; 144 } 145 } else { 146 badInputLength = 1; 147 throw new UnknownCharacterException(); 148 } 149 } else { 150 outputByte[0] = (byte)(theBytes >>8); 151 outputByte[1] = (byte)theBytes; 152 } 153 } 154 if (outputByte[0] == 0x00) 155 spaceNeeded = 1; 156 else 157 spaceNeeded = 2; 158 159 if (byteOff + spaceNeeded > outEnd) 160 throw new ConversionBufferFullException(); 161 162 if (spaceNeeded == 1) 163 output[byteOff++] = outputByte[1]; 164 else { 165 output[byteOff++] = outputByte[0]; 166 output[byteOff++] = outputByte[1]; 167 } 168 169 charOff += inputSize; 170 } 171 return byteOff - outOff; 172 } 173 174 /** 175 * Resets converter to its initial state. 176 */ 177 public void reset() { 178 charOff = byteOff = 0; 179 highHalfZoneCode = 0; 180 } 181 182 /** 183 * Returns the maximum number of bytes needed to convert a char. 184 */ 185 public int getMaxBytesPerChar() { 186 return 2; 187 } 188 189 /** 190 * Returns true if the given character can be converted to the 191 * target character encoding. 192 */ 193 public boolean canConvert(char c) { 194 return encodeChar(c) != UNMAPPABLE_ENCODING; 195 } 196 }