// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)EncoderStream.java, 1.5, 01/09/97





package marimba.io;





import java.io.*;





/**


 * A simple stream to encode a binary stream into an


 * ascii stream.


 *


 * @author Arthur van Hoff


 * @version 1.5, 01/09/97


 */


public class EncoderStream extends FilterOutputStream {


    int value;


    int bits;





    public EncoderStream(OutputStream out) {


	super(out);


    }





    /**


     * Encode a buffer.


     */


    public static byte[] encode(byte buf[], int len) {


	byte newbuf[] = new byte[((len * 8) + 5) / 6];


	FastOutputStream dest = new FastOutputStream(newbuf);


	try {


	    EncoderStream enc = new EncoderStream(dest);


	    enc.write(buf, 0, len);


	    enc.close();


	} catch (IOException e) {


	    e.printStackTrace();


	}


	return newbuf;


    }





    byte buf[] = new byte[1024];





    /**


     * Encode a buffer to an output stream.


     */


    public void write(byte data[], int off, int length) throws IOException {


	int j = 0;


	int c;


	int bits = this.bits;


	int value = this.value;


	byte buf[] = this.buf;


	int i = 0;


	


	while (j++ < length) {


	    c = data[off++] & 0xFF;


	    value = (value << 8) | c;


	    bits += 8;





	    while (bits >= 6) {


		bits -= 6;


		buf[i++] = (byte) (((value >> bits) & 0x3F) + 32);


		if (i == buf.length) {


		    out.write(buf, 0, i);


		    i = 0;


		}


	    }


	}


	this.bits = bits;


	this.value = value;


	if (i > 0) {


	    out.write(buf, 0, i);


	}


    }





    public void write(byte data[]) throws IOException {


	write(data, 0, data.length);


    }





    public void write(int c) throws IOException {


	value = (value << 8) | c;


	bits += 8;


	while (bits >= 6) {


	    bits -= 6;


	    out.write((byte) (((value >> bits) & 0x3F) + 32));


	}


    }





    public void finish() throws IOException {


	if (bits > 0) {


	    out.write((byte) (((value << (6 - bits)) & 0x3F) + 32));


	    bits = 0;


	}


	out.flush();


    }	





    public void close() throws IOException {


	finish();


	out.close();


    }


}


