home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / win95 / sieciowe / hotja32.lzh / hotjava / classsrc / java / util / ucencoder.java < prev    next >
Text File  |  1995-08-11  |  6KB  |  173 lines

  1. /*
  2.  * @(#)UCEncoder.java    1.6 95/03/17 Chuck McManis
  3.  *
  4.  * Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software
  7.  * and its documentation for NON-COMMERCIAL purposes and without
  8.  * fee is hereby granted provided that this copyright notice
  9.  * appears in all copies. Please refer to the file "copyright.html"
  10.  * for further important copyright and licensing information.
  11.  *
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  13.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  14.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  15.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  16.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  17.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  18.  */
  19. package java.util;
  20.  
  21. import java.io.OutputStream;
  22. import java.io.OutputStreamBuffer;
  23. import java.io.InputStream;
  24. import java.io.PrintStream;
  25.  
  26. /**
  27.  * This class implements a robust character encoder. The encoder is designed
  28.  * to convert binary data into printable characters. The characters are
  29.  * assumed to exist but they are not assumed to be ASCII, the complete set
  30.  * is 0-9, A-Z, a-z, "(", and ")".
  31.  *
  32.  * The basic encoding unit is a 3 character atom. It encodes two bytes
  33.  * of data. Bytes are encoded into a 64 character set, the characters
  34.  * were chosen specifically because they appear in all codesets.
  35.  * We don't care what their numerical equivalent is because
  36.  * we use a character array to map them. This is like UUencoding
  37.  * with the dependency on ASCII removed.
  38.  *
  39.  * The three chars that make up an atom are encoded as follows:
  40.  * <pre>
  41.  *      00xxxyyy 00axxxxx 00byyyyy
  42.  *      00 = leading zeros, all values are 0 - 63
  43.  *      xxxyyy - Top 3 bits of X, Top 3 bits of Y
  44.  *      axxxxx - a = X parity bit, xxxxx lower 5 bits of X
  45.  *      byyyyy - b = Y parity bit, yyyyy lower 5 bits of Y
  46.  * </pre>
  47.  *
  48.  * The atoms are arranged into lines suitable for inclusion into an
  49.  * email message or text file. The number of bytes that are encoded
  50.  * per line is 48 which keeps the total line length  under 80 chars)
  51.  *
  52.  * Each line has the form(
  53.  * <pre>
  54.  *  *(LLSS)(DDDD)(DDDD)(DDDD)...(CRC)
  55.  *  Where each (xxx) represents a three character atom.
  56.  *  (LLSS) - 8 bit length (high byte), and sequence number
  57.  *           modulo 256;
  58.  *  (DDDD) - Data byte atoms, if length is odd, last data 
  59.  *           atom has (DD00) (high byte data, low byte 0)
  60.  *  (CRC)  - 16 bit CRC for the line, includes length, 
  61.  *           sequence, and all data bytes. If there is a 
  62.  *           zero pad byte (odd length) it is _NOT_ 
  63.  *           included in the CRC.
  64.  * </pre>
  65.  *
  66.  * @version     1.6, 17 Mar 1995
  67.  * @author      Chuck McManis
  68.  * @see        CharacterEncoder
  69.  * @see        UCDecoder
  70.  */
  71. public class UCEncoder extends CharacterEncoder {
  72.  
  73.     /** this clase encodes two bytes per atom */
  74.     int bytesPerAtom() {
  75.     return (2);    
  76.     }
  77.  
  78.     /** this class encodes 48 bytes per line */
  79.     int bytesPerLine() {
  80.     return (48);
  81.     }
  82.  
  83.     /* this is the UCE mapping of 0-63 to characters .. */
  84.     private final static byte map_array[] = {
  85.                 //       0   1   2   3   4   5   6   7
  86.                         '0','1','2','3','4','5','6','7', // 0
  87.                         '8','9','A','B','C','D','E','F', // 1
  88.                         'G','H','I','J','K','L','M','N', // 2
  89.                         'O','P','Q','R','S','T','U','V', // 3
  90.                         'W','X','Y','Z','a','b','c','d', // 4
  91.                         'e','f','g','h','i','j','k','l', // 5
  92.                         'm','n','o','p','q','r','s','t', // 6
  93.                         'u','v','w','x','y','z','(',')'  // 7
  94.                 };
  95.  
  96.     private int sequence;
  97.     private byte tmp[] = new byte[2];
  98.     private CRC16 crc = new CRC16();
  99.  
  100.     /**
  101.      * encodeAtom - take two bytes and encode them into the correct
  102.      * three characters. If only one byte is to be encoded, the other
  103.      * must be zero. The padding byte is not included in the CRC computation.
  104.      */  
  105.     void encodeAtom(OutputStream outStream, byte data[], int offset, int len) {
  106.     int     i;
  107.     int     p1, p2; // parity bits
  108.     byte    a, b;
  109.  
  110.     a = data[offset];
  111.     if (len == 2) {
  112.         b = data[offset+1];
  113.     } else {
  114.         b = 0;
  115.     }
  116.     crc.update(a);
  117.     if (len == 2) {
  118.         crc.update(b);
  119.     }
  120.     outStream.write(map_array[((a >>> 2) & 0x38) + ((b >>> 5) & 0x7)]);
  121.     p1 = 0; p2 = 0;
  122.     for (i = 1; i < 256; i = i * 2) {
  123.         if ((a & i) != 0) {
  124.         p1++;
  125.         }
  126.         if ((b & i) != 0) {
  127.         p2++;
  128.         }
  129.     }
  130.     p1 = (p1 & 1) * 32;
  131.     p2 = (p2 & 1) * 32;
  132.     outStream.write(map_array[(a & 31) + p1]);
  133.     outStream.write(map_array[(b & 31) + p2]);
  134.     return;
  135.     }
  136.  
  137.     /**
  138.      * Each UCE encoded line starts with a prefix of '*[XXX]', where
  139.      * the sequence number and the length are encoded in the first
  140.      * atom.
  141.      */
  142.     void encodeLinePrefix(OutputStream outStream, int length) {
  143.     outStream.write('*');
  144.     crc.value = 0;
  145.     tmp[0] = (byte) length;
  146.     tmp[1] = (byte) sequence;
  147.     sequence = (sequence + 1) & 0xff;
  148.     encodeAtom(outStream, tmp, 0, 2);
  149.     } 
  150.  
  151.  
  152.     /**
  153.      * each UCE encoded line ends with YYY and encoded version of the
  154.      * 16 bit checksum. The most significant byte of the check sum
  155.      * is always encoded FIRST.
  156.      */
  157.     void encodeLineSuffix(OutputStream outStream) {
  158.     tmp[0] = (byte) ((crc.value >>> 8) & 0xff);
  159.     tmp[1] = (byte) (crc.value & 0xff);
  160.     encodeAtom(outStream, tmp, 0, 2);
  161.     super.pStream.println();
  162.     }
  163.  
  164.     /**
  165.      * The buffer prefix code is used to initialize the sequence number
  166.      * to zero.
  167.      */
  168.     void encodeBufferPrefix(OutputStream a) { 
  169.     sequence = 0;
  170.     super.encodeBufferPrefix(a);
  171.     }
  172. }
  173.