1 /* 2 * Copyright (c) 1997, 2001, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.io; 27 28 /** 29 * An algorithmic conversion from ISO 2022 to Unicode 30 * 31 * @author Tom Zhou 32 */ 33 public abstract class ByteToCharISO2022 extends ByteToCharConverter 34 { 35 // Value to be filled by subclass 36 protected String SODesignator[]; 37 protected String SS2Designator[] = null; 38 protected String SS3Designator[] = null; 39 40 protected ByteToCharConverter SOConverter[]; 41 protected ByteToCharConverter SS2Converter[] = null; 42 protected ByteToCharConverter SS3Converter[] = null; 43 44 private static final byte ISO_ESC = 0x1b; 45 private static final byte ISO_SI = 0x0f; 46 private static final byte ISO_SO = 0x0e; 47 private static final byte ISO_SS2_7 = 0x4e; 48 private static final byte ISO_SS3_7 = 0x4f; 49 private static final byte MSB = (byte)0x80; 50 private static final char REPLACE_CHAR = '\uFFFD'; 51 private static final byte maximumDesignatorLength = 3; 52 53 private static final byte SOFlag = 0; 54 private static final byte SS2Flag = 1; 55 private static final byte SS3Flag = 2; 56 private static final byte G0 = 0; 57 private static final byte G1 = 1; 58 59 private ByteToCharConverter tmpConverter[]; 60 61 private int curSODes, curSS2Des, curSS3Des; 62 private boolean shiftout; 63 64 private byte remainByte[] = new byte[10]; 65 private int remainIndex = -1; 66 private byte state, firstByte; 67 68 public void reset() 69 { 70 int i = 0; 71 72 shiftout = false; 73 state = G0; 74 firstByte = 0; 75 76 curSODes = 0; 77 curSS2Des = 0; 78 curSS3Des = 0; 79 80 charOff = byteOff = 0; 81 remainIndex = -1; 82 83 for(i = 0; i < remainByte.length; i++) 84 remainByte[i] = 0; 85 } 86 87 public int flush(char[] output, int outStart, int outEnd) 88 throws MalformedInputException 89 { 90 int i; 91 if (state != G0) { 92 badInputLength = 0; 93 throw new MalformedInputException(); 94 } 95 reset(); 96 return 0; 97 } 98 99 private byte[] savetyGetSrc(byte[] input, int inOff, int inEnd, int nbytes) 100 { 101 int i; 102 byte tmp[]; 103 104 if(inOff <= (inEnd-nbytes+1)) 105 tmp = new byte[nbytes]; 106 else 107 tmp = new byte[inEnd-inOff]; 108 109 for(i = 0; i < tmp.length; i++) 110 tmp[i] = input[inOff+i]; 111 return tmp; 112 } 113 114 private char getUnicode(byte byte1, byte byte2, byte shiftFlag) 115 { 116 byte1 |= MSB; 117 byte2 |= MSB; 118 119 byte[] tmpByte = {byte1,byte2}; 120 char[] tmpChar = new char[1]; 121 int i = 0, 122 tmpIndex = 0; 123 124 switch(shiftFlag) { 125 case SOFlag: 126 tmpIndex = curSODes; 127 tmpConverter = SOConverter; 128 break; 129 case SS2Flag: 130 tmpIndex = curSS2Des; 131 tmpConverter = SS2Converter; 132 break; 133 case SS3Flag: 134 tmpIndex = curSS3Des; 135 tmpConverter = SS3Converter; 136 break; 137 } 138 139 for(i = 0; i < tmpConverter.length; i++) { 140 if(tmpIndex == i) { 141 try { 142 tmpConverter[i].convert(tmpByte, 0, 2, tmpChar, 0, 1); 143 } catch (Exception e) {} 144 return tmpChar[0]; 145 } 146 } 147 return REPLACE_CHAR; 148 } 149 150 public final int convert(byte[] input, int inOff, int inEnd, 151 char[] output, int outOff, int outEnd) 152 throws ConversionBufferFullException, 153 MalformedInputException 154 { 155 int i; 156 int DesignatorLength = 0; 157 charOff = outOff; 158 byteOff = inOff; 159 160 // Loop until we hit the end of the input 161 while (byteOff < inEnd) { 162 // If we don't have room for the output, throw an exception 163 if (charOff >= outEnd) 164 throw new ConversionBufferFullException(); 165 if(remainIndex < 0) { 166 remainByte[0] = input[byteOff]; 167 remainIndex = 0; 168 byteOff++; 169 } 170 switch (remainByte[0]) { 171 case ISO_SO: 172 shiftout = true; 173 if(remainIndex > 0) 174 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex); 175 remainIndex--; 176 break; 177 case ISO_SI: 178 shiftout = false; 179 if(remainIndex > 0) 180 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex); 181 remainIndex--; 182 break; 183 case ISO_ESC: 184 byte tmp[] = savetyGetSrc(input, byteOff, inEnd, 185 (maximumDesignatorLength-remainIndex)); 186 System.arraycopy(tmp, 0, remainByte, remainIndex+1, tmp.length); 187 remainIndex += tmp.length; 188 byteOff += tmp.length; 189 if(tmp.length<(maximumDesignatorLength-remainIndex)) 190 break; 191 String tmpString = new String(remainByte, 1, remainIndex); 192 for (i = 0; i < SODesignator.length; i++) { 193 if(tmpString.indexOf(SODesignator[i]) == 0) { 194 curSODes = i; 195 DesignatorLength = SODesignator[i].length(); 196 break; 197 } 198 } 199 200 if (DesignatorLength == 0 ) { // Designator not recognized 201 badInputLength = tmp.length; 202 throw new MalformedInputException(); 203 } 204 205 if (i == SODesignator.length) { 206 for (i = 0; i < SS2Designator.length; i++) { 207 if(tmpString.indexOf(SS2Designator[i]) == 0) { 208 curSS2Des = i; 209 DesignatorLength = SS2Designator[i].length(); 210 break; 211 } 212 } 213 if(i == SS2Designator.length) { 214 for(i = 0; i < SS3Designator.length; i++) { 215 if (tmpString.indexOf(SS3Designator[i]) == 0) { 216 curSS3Des = i; 217 DesignatorLength = SS3Designator[i].length(); 218 break; 219 } 220 } 221 if (i == SS3Designator.length) { 222 switch(remainByte[1]) { 223 case ISO_SS2_7: 224 output[charOff] = getUnicode(remainByte[2], 225 remainByte[3], 226 SS2Flag); 227 charOff++; 228 DesignatorLength = 3; 229 break; 230 case ISO_SS3_7: 231 output[charOff] = getUnicode(remainByte[2], 232 remainByte[3], 233 SS3Flag); 234 charOff++; 235 DesignatorLength = 3; 236 break; 237 default: 238 DesignatorLength = 0; 239 } 240 } 241 } 242 } 243 if (remainIndex > DesignatorLength) { 244 for(i = 0; i < remainIndex-DesignatorLength; i++) 245 remainByte[i] = remainByte[DesignatorLength+1+i]; 246 remainIndex = i-1; 247 } else { 248 remainIndex = -1; 249 } 250 break; 251 default: 252 if (!shiftout) { 253 output[charOff] = (char)remainByte[0]; 254 charOff++; 255 } else { 256 switch (state) { 257 case G0: 258 firstByte = remainByte[0]; 259 state = G1; 260 break; 261 case G1: 262 output[charOff] = getUnicode(firstByte, remainByte[0], 263 SOFlag); 264 charOff++; 265 state = G0; 266 break; 267 } 268 } 269 if (remainIndex > 0) 270 System.arraycopy(remainByte, 1, remainByte, 0, remainIndex); 271 remainIndex--; 272 } 273 } 274 return charOff - outOff; 275 } 276 }