1 /* 2 * Copyright 1996-2003 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 26 package sun.io; 27 28 import sun.nio.cs.ext.EUC_TW; 29 30 /* 31 * @author Limin Shi 32 */ 33 34 public class CharToByteEUC_TW extends CharToByteConverter 35 { 36 private final byte MSB = (byte)0x80; 37 private final byte SS2 = (byte) 0x8E; 38 private final byte P2 = (byte) 0xA2; 39 private final byte P3 = (byte) 0xA3; 40 41 private final static EUC_TW nioCoder = new EUC_TW(); 42 43 private static String uniTab1 = nioCoder.getUniTab1(); 44 private static String uniTab2 = nioCoder.getUniTab2(); 45 private static String uniTab3 = nioCoder.getUniTab3(); 46 private static String cnsTab1 = nioCoder.getCNSTab1(); 47 private static String cnsTab2 = nioCoder.getCNSTab2(); 48 private static String cnsTab3 = nioCoder.getCNSTab3(); 49 50 public int flush(byte[] output, int outStart, int outEnd) 51 throws MalformedInputException 52 { 53 reset(); 54 return 0; 55 } 56 57 public void reset() { 58 byteOff = charOff = 0; 59 } 60 61 public boolean canConvert(char ch){ 62 if (((0xFF00 & ch) != 0) && (getNative(ch) != -1)){ 63 return true; 64 } 65 return false; 66 } 67 68 /** 69 * Character conversion 70 */ 71 public int convert(char[] input, int inOff, int inEnd, 72 byte[] output, int outOff, int outEnd) 73 throws UnknownCharacterException, MalformedInputException, 74 ConversionBufferFullException 75 { 76 int outputSize; 77 byte [] tmpbuf = new byte[4]; 78 byte [] outputByte; 79 80 byteOff = outOff; 81 82 //Fixed 4122961 by bringing the charOff++ out to this 83 // loop where it belongs, changing the loop from 84 // while(){} to for(){}. 85 for (charOff = inOff; charOff < inEnd; charOff++) { 86 outputByte = tmpbuf; 87 if ( input[charOff] < 0x80) { // ASCII 88 outputSize = 1; 89 outputByte[0] = (byte)(input[charOff] & 0x7f); 90 } else { 91 outputSize = unicodeToEUC(input[charOff], outputByte); 92 } 93 94 if (outputSize == -1) { 95 if (subMode) { 96 outputByte = subBytes; 97 outputSize = subBytes.length; 98 } else { 99 badInputLength = 1; 100 throw new UnknownCharacterException(); 101 } 102 } 103 104 if (outEnd - byteOff < outputSize) 105 throw new ConversionBufferFullException(); 106 107 for (int i = 0; i < outputSize; i++) 108 output[byteOff++] = outputByte[i]; 109 } 110 111 return byteOff - outOff; 112 113 } 114 115 116 /** 117 * returns the maximum number of bytes needed to convert a char 118 */ 119 public int getMaxBytesPerChar() { 120 return 4; 121 } 122 123 124 /** 125 * Return the character set ID 126 */ 127 public String getCharacterEncoding() { 128 return "EUC_TW"; 129 } 130 131 132 protected int getNative(char unicode) { 133 int i, 134 cns; // 2 chars in CNS table make 1 CNS code 135 136 if (unicode < UniTab2[0]) { 137 if ((i = searchTab(unicode, UniTab1)) == -1) 138 return -1; 139 cns = (CNSTab1[2*i] << 16) + CNSTab1[2*i+1]; 140 return cns; 141 } else if (unicode < UniTab3[0]) { 142 if ((i = searchTab(unicode, UniTab2)) == -1) 143 return -1; 144 cns = (CNSTab2[2*i] << 16) + CNSTab2[2*i+1]; 145 return cns; 146 } else { 147 if ((i = searchTab(unicode, UniTab3)) == -1) 148 return -1; 149 cns = (CNSTab3[2*i] << 16) + CNSTab3[2*i+1]; 150 return cns; 151 } 152 } 153 154 protected int searchTab(char code, char [] table) { 155 int i = 0, l, h; 156 157 for (l = 0, h = table.length - 1; l < h; ) { 158 if (table[l] == code) { 159 i = l; 160 break; 161 } 162 if (table[h] == code) { 163 i = h; 164 break; 165 } 166 i = (l + h) / 2; 167 if (table[i] == code) 168 break; 169 if (table[i] < code) 170 l = i + 1; 171 else h = i - 1; 172 } 173 if (code == table[i]) { 174 return i; 175 } else { 176 return -1; 177 } 178 } 179 180 181 private int unicodeToEUC(char unicode, byte ebyte[]) { 182 int cns = getNative(unicode); 183 184 if ((cns >> 16) == 0x01) { // Plane 1 185 ebyte[0] = (byte) (((cns & 0xff00) >> 8) | MSB); 186 ebyte[1] = (byte) ((cns & 0xff) | MSB); 187 return 2; 188 } 189 190 byte cnsPlane = (byte)(cns >> 16); 191 if (cnsPlane >= (byte)0x02) { // Plane 2 192 ebyte[0] = SS2; 193 ebyte[1] = (byte) (cnsPlane | (byte)0xA0); 194 ebyte[2] = (byte) (((cns & 0xff00) >> 8) | MSB); 195 ebyte[3] = (byte) ((cns & 0xff) | MSB); 196 return 4; 197 } 198 199 return -1; 200 } 201 202 protected int unicodeToEUC(char unicode) { 203 if (unicode <= 0x7F) { // ASCII falls into EUC_TW CS0 204 return unicode; 205 } 206 207 int cns = getNative(unicode); 208 int plane = cns >> 16; 209 int euc = (cns & 0x0000FFFF) | 0x00008080; 210 211 if (plane == 1) { 212 return euc; 213 } else if (plane == 2) { 214 return ((SS2 << 24) & 0xFF000000) | ((P2 << 16) & 0x00FF0000) | 215 euc; 216 } else if (plane == 3) { 217 return ((SS2 << 24) & 0xFF000000) | ((P3 << 16) & 0x00FF0000) | 218 euc; 219 } 220 221 return -1; 222 } 223 224 private char [] UniTab1 = uniTab1.toCharArray(); 225 private char [] UniTab2 = uniTab2.toCharArray(); 226 private char [] UniTab3 = uniTab3.toCharArray(); 227 private char [] CNSTab1 = cnsTab1.toCharArray(); 228 private char [] CNSTab2 = cnsTab2.toCharArray(); 229 private char [] CNSTab3 = cnsTab3.toCharArray(); 230 }