1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22/* 23 * ident "%Z%%M% %I% %E% SMI" 24 * 25 * Copyright (c) 1999-2000 by Sun Microsystems, Inc. 26 * All rights reserved. 27 */ 28 29/** 30 * Copyright 1996 Active Software Inc. 31 */ 32 33package sunsoft.jws.visual.rt.encoding; 34 35import java.io.*; 36 37// Referenced classes of package sunsoft.jws.visual.rt.encoding: 38// CEStreamExhausted, CRC16 39 40public class UCDecoder 41{ 42 43 protected int bytesPerAtom() 44 { 45 return 2; 46 } 47 48 protected int bytesPerLine() 49 { 50 return 48; 51 } 52 53 protected void decodeAtom(InputStream inStream, 54 OutputStream outStream, int l) 55 throws IOException 56 { 57 byte a = -1; 58 byte b = -1; 59 byte c = -1; 60 byte tmp[] = new byte[3]; 61 int i = inStream.read(tmp); 62 if (i != 3) 63 throw new CEStreamExhausted(); 64 for (i = 0; i < 64 && (a == -1 || b == -1 || c == -1); i++) 65 { 66 if (tmp[0] == map_array[i]) 67 a = (byte)i; 68 if (tmp[1] == map_array[i]) 69 b = (byte)i; 70 if (tmp[2] == map_array[i]) 71 c = (byte)i; 72 } 73 74 byte high_byte = (byte)(((a & 0x38) << 2) + (b & 0x1f)); 75 byte low_byte = (byte)(((a & 0x7) << 5) + (c & 0x1f)); 76 int p1 = 0; 77 int p2 = 0; 78 for (i = 1; i < 256; i *= 2) 79 { 80 if ((high_byte & i) != 0) 81 p1++; 82 if ((low_byte & i) != 0) 83 p2++; 84 } 85 86 int np1 = (b & 0x20) / 32; 87 int np2 = (c & 0x20) / 32; 88 if ((p1 & 0x1) != np1) 89 throw new IOException("UCDecoder: High byte parity error."); 90 if ((p2 & 0x1) != np2) 91 throw new IOException("UCDecoder: Low byte parity error."); 92 outStream.write(high_byte); 93 crc.update(high_byte); 94 if (l == 2) 95 { 96 outStream.write(low_byte); 97 crc.update(low_byte); 98 } 99 } 100 101 protected void decodeBufferPrefix(InputStream inStream, 102 OutputStream outStream) 103 { 104 sequence = 0; 105 } 106 107 protected int decodeLinePrefix(InputStream inStream, 108 OutputStream outStream) 109 throws IOException 110 { 111 crc.value = 0; 112 do 113 { 114 int c = inStream.read(tmp, 0, 1); 115 if (c == -1) 116 throw new CEStreamExhausted(); 117 } 118 while (tmp[0] != 42); 119 lineAndSeq.reset(); 120 decodeAtom(inStream, lineAndSeq, 2); 121 byte xtmp[] = lineAndSeq.toByteArray(); 122 int nLen = xtmp[0] & 0xff; 123 int nSeq = xtmp[1] & 0xff; 124 if (nSeq != sequence) 125 { 126 throw new IOException("UCDecoder: Out of sequence line."); 127 } 128 else 129 { 130 sequence = sequence + 1 & 0xff; 131 return nLen; 132 } 133 } 134 135 protected void decodeLineSuffix(InputStream inStream, 136 OutputStream outStream) 137 throws IOException 138 { 139 int lineCRC = crc.value; 140 lineAndSeq.reset(); 141 decodeAtom(inStream, lineAndSeq, 2); 142 byte tmp[] = lineAndSeq.toByteArray(); 143 int readCRC = (tmp[0] << 8 & 0xff00) + (tmp[1] & 0xff); 144 if (readCRC != lineCRC) 145 throw new IOException("UCDecoder: CRC check failed."); 146 else 147 return; 148 } 149 150 public void decodeBuffer(InputStream aStream, OutputStream bStream) 151 throws IOException 152 { 153 int totalBytes = 0; 154 decodeBufferPrefix(aStream, bStream); 155 try 156 { 157 do 158 { 159 int length = decodeLinePrefix(aStream, bStream); 160 int i; 161 for (i = 0; i + bytesPerAtom() < length; 162 i += bytesPerAtom()) 163 { 164 decodeAtom(aStream, bStream, bytesPerAtom()); 165 totalBytes += bytesPerAtom(); 166 } 167 168 if (i + bytesPerAtom() == length) 169 { 170 decodeAtom(aStream, bStream, bytesPerAtom()); 171 totalBytes += bytesPerAtom(); 172 } 173 else 174 { 175 decodeAtom(aStream, bStream, length - i); 176 totalBytes += length - i; 177 } 178 decodeLineSuffix(aStream, bStream); 179 } 180 while (true); 181 } 182 catch (CEStreamExhausted ex) 183 { 184 decodeBufferSuffix(aStream, bStream); 185 } 186 } 187 188 public byte[] decodeBuffer(String inputString) 189 throws IOException 190 { 191 byte inputBuffer[] = new byte[inputString.length()]; 192 inputString.getBytes(0, inputString.length(), inputBuffer, 0); 193 ByteArrayInputStream inStream = 194 new ByteArrayInputStream(inputBuffer); 195 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 196 decodeBuffer(inStream, outStream); 197 return outStream.toByteArray(); 198 } 199 200 protected void decodeBufferSuffix(InputStream inputstream, 201 OutputStream outputstream) 202 throws IOException 203 { 204 } 205 206 public UCDecoder() 207 { 208 super(); 209 tmp = new byte[2]; 210 crc = new CRC16(); 211 lineAndSeq = new ByteArrayOutputStream(2); 212 } 213 214 private static final byte map_array[] = { 215 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 216 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 217 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 218 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 219 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 220 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 221 121, 122, 40, 41 222 }; 223 private int sequence; 224 private byte tmp[]; 225 CRC16 crc; 226 private ByteArrayOutputStream lineAndSeq; 227 228} 229