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 public abstract class ByteToCharDBCS_EBCDIC extends ByteToCharConverter 28 { 29 30 private static final int SBCS = 0; 31 private static final int DBCS = 1; 32 33 private static final int SO = 0x0e; 34 private static final int SI = 0x0f; 35 36 private int currentState; 37 private boolean savedBytePresent; 38 private byte savedByte; 39 40 protected String singleByteToChar; 41 protected short index1[]; 42 protected String index2; 43 protected int mask1; 44 protected int mask2; 45 protected int shift; 46 47 48 public ByteToCharDBCS_EBCDIC() { 49 super(); 50 currentState = SBCS; 51 savedBytePresent = false; 52 } 53 54 public int flush(char [] output, int outStart, int outEnd) 55 throws MalformedInputException 56 { 57 58 if (savedBytePresent) { 59 reset(); 60 badInputLength = 0; 61 throw new MalformedInputException(); 62 } 63 64 reset(); 65 return 0; 66 } 67 68 /** 69 * Character conversion 70 */ 71 public int convert(byte[] input, int inOff, int inEnd, 72 char[] output, int outOff, int outEnd) 73 throws UnknownCharacterException, MalformedInputException, 74 ConversionBufferFullException 75 { 76 int inputSize; 77 char outputChar = '\uFFFD'; 78 79 charOff = outOff; 80 byteOff = inOff; 81 82 while(byteOff < inEnd) { 83 int byte1, byte2; 84 int v; 85 86 if (!savedBytePresent) { 87 byte1 = input[byteOff]; 88 inputSize = 1; 89 } else { 90 byte1 = savedByte; 91 savedBytePresent = false; 92 inputSize = 0; 93 } 94 95 if (byte1 == SO) { 96 97 // For SO characters - simply validate the state and if OK 98 // update the state and go to the next byte 99 100 if (currentState != SBCS) { 101 badInputLength = 1; 102 throw new MalformedInputException(); 103 } else { 104 currentState = DBCS; 105 byteOff += inputSize; 106 } 107 } 108 109 else 110 if (byte1 == SI) { 111 // For SI characters - simply validate the state and if OK 112 // update the state and go to the next byte 113 114 if (currentState != DBCS) { 115 badInputLength = 1; 116 throw new MalformedInputException(); 117 } else { 118 currentState = SBCS; 119 byteOff+= inputSize; 120 } 121 } else { 122 123 // Process the real data characters 124 125 if (byte1 < 0) 126 byte1 += 256; 127 128 if (currentState == SBCS) { 129 outputChar = singleByteToChar.charAt(byte1); 130 } else { 131 132 // for a DBCS character - architecture dictates the 133 // valid range of 1st bytes 134 135 if (byte1 < 0x40 || byte1 > 0xfe) { 136 badInputLength = 1; 137 throw new MalformedInputException(); 138 } 139 140 if (byteOff + inputSize >= inEnd) { 141 // We have been split in the middle if a character 142 // save the first byte for next time around 143 144 savedByte = (byte)byte1; 145 savedBytePresent = true; 146 byteOff += inputSize; 147 break; 148 } 149 150 byte2 = input[byteOff+inputSize]; 151 if (byte2 < 0) 152 byte2 += 256; 153 154 inputSize++; 155 156 // validate the pair of bytes meet the architecture 157 158 if ((byte1 != 0x40 || byte2 != 0x40) && 159 (byte2 < 0x41 || byte2 > 0xfe)) { 160 badInputLength = 2; 161 throw new MalformedInputException(); 162 } 163 164 // Lookup in the two level index 165 v = byte1 * 256 + byte2; 166 outputChar = index2.charAt(index1[((v & mask1) >> shift)] + (v & mask2)); 167 } 168 169 if (outputChar == '\uFFFD') { 170 if (subMode) 171 outputChar = subChars[0]; 172 else { 173 badInputLength = inputSize; 174 throw new UnknownCharacterException(); 175 } 176 } 177 178 if (charOff >= outEnd) 179 throw new ConversionBufferFullException(); 180 181 output[charOff++] = outputChar; 182 byteOff += inputSize; 183 } 184 185 } 186 187 return charOff - outOff; 188 } 189 190 191 /** 192 * Resets the converter. 193 */ 194 public void reset() { 195 charOff = byteOff = 0; 196 currentState = SBCS; 197 savedBytePresent = false; 198 } 199 }