Mega Code Archive

 
Categories / Java / Development Class
 

Add a ASCII85 encoding to the stream

/*  * Licensed to the Apache Software Foundation (ASF) under one or more  * contributor license agreements.  See the NOTICE file distributed with  * this work for additional information regarding copyright ownership.  * The ASF licenses this file to You under the Apache License, Version 2.0  * (the "License"); you may not use this file except in compliance with  * the License.  You may obtain a copy of the License at  *   *      http://www.apache.org/licenses/LICENSE-2.0  *   * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ /* $Id: ASCII85OutputStream.java 426584 2006-07-28 16:01:47Z jeremias $ */ import java.io.OutputStream; import java.io.FilterOutputStream; import java.io.IOException; /**  * This class applies a ASCII85 encoding to the stream.  *  * @version $Id: ASCII85OutputStream.java 426584 2006-07-28 16:01:47Z jeremias $  */ public class ASCII85OutputStream extends FilterOutputStream             implements ASCII85Constants {     private static final boolean DEBUG = false;     private int pos = 0;     private long buffer = 0;     private int posinline = 0;     private int bw = 0;     /** @see java.io.FilterOutputStream **/     public ASCII85OutputStream(OutputStream out) {         super(out);     }     /** @see java.io.FilterOutputStream **/     public void write(int b) throws IOException {         if (pos == 0) {             buffer += (b << 24) & 0xff000000L;         } else if (pos == 1) {             buffer += (b << 16) & 0xff0000L;         } else if (pos == 2) {             buffer += (b << 8) & 0xff00L;         } else {             buffer += b & 0xffL;         }         pos++;         if (pos > 3) {             checkedWrite(convertWord(buffer));             buffer = 0;             pos = 0;         }     }     /* UNUSED ATM     private void checkedWrite(int b) throws IOException {         if (posinline == 80) {             out.write(EOL); bw++;             posinline = 0;         }         checkedWrite(b);         posinline++;         bw++;     }*/     private void checkedWrite(byte[] buf) throws IOException {         checkedWrite(buf, buf.length, false);     }     private void checkedWrite(byte[] buf, boolean nosplit) throws IOException {         checkedWrite(buf, buf.length, nosplit);     }     private void checkedWrite(byte[] buf , int len) throws IOException {         checkedWrite(buf, len, false);     }     private void checkedWrite(byte[] buf , int len, boolean nosplit) throws IOException {         if (posinline + len > 80) {             int firstpart = (nosplit ? 0 : len - (posinline + len - 80));             if (firstpart > 0) {                 out.write(buf, 0, firstpart);             }             out.write(EOL); bw++;             int rest = len - firstpart;             if (rest > 0) {                 out.write(buf, firstpart, rest);             }             posinline = rest;         } else {             out.write(buf, 0, len);             posinline += len;         }         bw += len;     }     /**      * This converts a 32 bit value (4 bytes) into 5 bytes using base 85.      * each byte in the result starts with zero at the '!' character so      * the resulting base85 number fits into printable ascii chars      *      * @param word the 32 bit unsigned (hence the long datatype) word      * @return 5 bytes (or a single byte of the 'z' character for word      * values of 0)      */     private byte[] convertWord(long word) {         word = word & 0xffffffff;         if (word == 0) {             return ZERO_ARRAY;         } else {             if (word < 0) {                 word = -word;             }             byte c1 =                 (byte)((word                         / POW85[0]) & 0xFF);             byte c2 =                 (byte)(((word - (c1 * POW85[0]))                         / POW85[1]) & 0xFF);             byte c3 =                 (byte)(((word - (c1 * POW85[0])                               - (c2 * POW85[1]))                         / POW85[2]) & 0xFF);             byte c4 =                 (byte)(((word - (c1 * POW85[0])                               - (c2 * POW85[1])                               - (c3 * POW85[2]))                         / POW85[3]) & 0xFF);             byte c5 =                 (byte)(((word - (c1 * POW85[0])                               - (c2 * POW85[1])                               - (c3 * POW85[2])                               - (c4 * POW85[3])))                         & 0xFF);             byte[] ret = {                 (byte)(c1 + START), (byte)(c2 + START),                 (byte)(c3 + START), (byte)(c4 + START),                 (byte)(c5 + START)             };             if (DEBUG) {                 for (int i = 0; i < ret.length; i++) {                     if (ret[i] < 33 || ret[i] > 117) {                         System.out.println("Illegal char value "                                         + new Integer(ret[i]));                     }                 }             }             return ret;         }     }     /** @see Finalizable **/     public void finalizeStream() throws IOException {         // now take care of the trailing few bytes.         // with n leftover bytes, we append 0 bytes to make a full group of 4         // then convert like normal (except not applying the special zero rule)         // and write out the first n+1 bytes from the result         if (pos > 0) {             int rest = pos;             /*             byte[] lastdata = new byte[4];             int i = 0;             for (int j = 0; j < 4; j++) {                 if (j < rest) {                     lastdata[j] = data[i++];                 } else {                     lastdata[j] = 0;                 }             }             long val = ((lastdata[0] << 24) & 0xff000000L)                        + ((lastdata[1] << 16) & 0xff0000L)                        + ((lastdata[2] << 8) & 0xff00L)                        + (lastdata[3] & 0xffL);             */             byte[] conv;             // special rule for handling zeros at the end             if (buffer != 0) {                 conv = convertWord(buffer);             } else {                 conv = new byte[5];                 for (int j = 0; j < 5; j++) {                     conv[j] = (byte)'!';                 }             }             // assert rest+1 <= 5             checkedWrite(conv, rest + 1);         }         // finally write the two character end of data marker         checkedWrite(EOD, true);         flush();        }     /** @see java.io.FilterOutputStream **/     public void close() throws IOException {         finalizeStream();         super.close();     } } /*  * Licensed to the Apache Software Foundation (ASF) under one or more  * contributor license agreements.  See the NOTICE file distributed with  * this work for additional information regarding copyright ownership.  * The ASF licenses this file to You under the Apache License, Version 2.0  * (the "License"); you may not use this file except in compliance with  * the License.  You may obtain a copy of the License at  *   *      http://www.apache.org/licenses/LICENSE-2.0  *   * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ /* $Id: ASCII85Constants.java 426584 2006-07-28 16:01:47Z jeremias $ */   /**  * This interface defines constants used by the ASCII85 filters.  *  * @version $Id: ASCII85Constants.java 426584 2006-07-28 16:01:47Z jeremias $  */ interface ASCII85Constants {     /** Special character "z" stands for four NULL bytes (short-cut for !!!!!) */     public static final int ZERO          = 0x7A; //"z"     /** ZERO as a byte array */     public static final byte[] ZERO_ARRAY = {(byte)ZERO};     /** The start index for ASCII85 characters (!) */     public static final int START         = 0x21; //"!"     /** The end index for ASCII85 characters (u) */     public static final int END           = 0x75; //"u"     /** The EOL indicator (LF) */     public static final int EOL           = 0x0A; //"\n"     /** The EOD (end of data) indicator */     public static final byte[] EOD        = {0x7E, 0x3E}; //"~>"     /** Array of powers of 85 (4, 3, 2, 1, 0) */     public static final long POW85[] = new long[] {85 * 85 * 85 * 85,                                                      85 * 85 * 85,                                                     85 * 85,                                                     85,                                                     1};     /*     public static final long BASE85_4 = 85;     public static final long BASE85_3 = BASE85_4 * BASE85_4;     public static final long BASE85_2 = BASE85_3 * BASE85_4;     public static final long BASE85_1 = BASE85_2 * BASE85_4;     */ }