/* ================================================================== * RFC1924OutputStream.java - May 15, 2013 6:42:26 AM * * Copyright 2007-2013 SolarNetwork.net Dev Team * * Adapted from libxjava original source. * * Copyright (c) 2010 Marcel Patzlaff (marcel.patzlaff@gmail.com) * * This library is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library. If not, see <http://www.gnu.org/licenses/>. * ================================================================== */ package net.solarnetwork.io; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; /** * Encode binary data into ASCII85 form based on RFC 1924. * * @author matt * @version 1.0 */ public class RFC1924OutputStream extends FilterOutputStream { static final byte[] ENCODABET = new byte[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*', '+', '-', ';', '<', '=', '>', '?', '@', '^', '_', '`', '{', '|', '}', '~' }; static final long[] FACTORS = { 1, // 85^0 85, // 85^1 7225, // 85^2 614125, // 85^3 52200625 // 85^4 }; private final int[] tuple = new int[4]; private int bIndex = 0; /** * Construct with OutputStream to filter. * * @param out * the output stream */ public RFC1924OutputStream(OutputStream out) { super(out); } private void writeTuple() throws IOException { int bytes; long sum = 0; for ( bytes = 0; bytes < bIndex; bytes++ ) { sum = (sum << 8) | tuple[bytes]; } if ( bytes == 4 ) { for ( int e = 4; e >= 0; e-- ) { super.write(ENCODABET[(int) (sum / FACTORS[e])]); sum %= FACTORS[e]; } sum = 0; bytes = 0; } else if ( bytes > 0 ) { for ( int e = bytes; e >= 0; e-- ) { super.write(ENCODABET[(int) (sum / FACTORS[e])]); sum %= FACTORS[e]; } } } @Override public void write(int b) throws IOException { tuple[bIndex++] = b & 0xFF; if ( bIndex >= tuple.length ) { writeTuple(); bIndex = 0; } } @Override public void close() throws IOException { if ( bIndex > 0 && bIndex < tuple.length ) { writeTuple(); bIndex = -1; flush(); } } }