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 
33 package sunsoft.jws.visual.rt.encoding;
34 
35 import java.io.*;
36 
37 // Referenced classes of package sunsoft.jws.visual.rt.encoding:
38 //            CEStreamExhausted, CRC16
39 
40 public class UCDecoder
41 {
42 
bytesPerAtom()43     protected int bytesPerAtom()
44     {
45         return 2;
46     }
47 
bytesPerLine()48     protected int bytesPerLine()
49     {
50         return 48;
51     }
52 
decodeAtom(InputStream inStream, OutputStream outStream, int l)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 
decodeBufferPrefix(InputStream inStream, OutputStream outStream)101     protected void decodeBufferPrefix(InputStream inStream,
102 				      OutputStream outStream)
103     {
104         sequence = 0;
105     }
106 
decodeLinePrefix(InputStream inStream, OutputStream outStream)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 
decodeLineSuffix(InputStream inStream, OutputStream outStream)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 
decodeBuffer(InputStream aStream, OutputStream bStream)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 
decodeBuffer(String inputString)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 
decodeBufferSuffix(InputStream inputstream, OutputStream outputstream)200     protected void decodeBufferSuffix(InputStream inputstream,
201 				      OutputStream outputstream)
202 	throws IOException
203     {
204     }
205 
UCDecoder()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