/* * * FileName: ByteUnPackInputStream.java * * * $Author: konki $ * Author(s): konki * * * Objective: * Enable reading data to an internal buffer for easy data reception * * * $Log: ByteUnPackInputStream.java,v $ # Revision 1.3 1996/04/01 21:23:06 konki # Added expand( int size ) # # Revision 1.2 1996/02/21 00:24:48 konki # fixed some comments # # Revision 1.1 1996/02/18 23:09:35 konki # Initial revision # * Change Log: * Created on Fri Feb 9 12:13:13 EST 1996 * Changes: Date Initials * * * Notes: * $Id: ByteUnPackInputStream.java,v 1.3 1996/04/01 21:23:06 konki Exp $ * */ package wb; import java.io.*; import java.lang.*; /** * This class lets you read primitive Java data types * from a local byte array after the data is read in one single block * in a portable way. Primitive data types are well * understood types with associated operations. For example, an * Integer is considered to be a good primitive data type. * * The byte data can be generated using a BytePackOutputStream. */ public class ByteUnPackInputStream { /** * The buffer where data is stored. */ protected byte buf[]; /** * The number of bytes in the buffer. */ protected int count; /** * Read index of the local byte buffer */ private int rindex; /** * The real stream from which the byte array will be filled with data */ protected InputStream instream; /** * Reads one byte and returns it as an integer. * Assumes that the byte array has at least one byte. * @return the int value of the byte */ private int getInt() { return( (buf[rindex++] & 0xFF) ); } /** * Private method to expand the size of the local buffer to accommodate * new data. grows in step of 512 bytes. */ private synchronized void expand() { byte newbuf[] = new byte[buf.length+512]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } /** * Private method to expand the size of the local buffer to accommodate * new data. grows in step of 512 bytes. */ private synchronized void expand(int num) { byte newbuf[] = new byte[buf.length+num+128]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } /** * Creates a new ByteUnPackInputStream. * @param in the output stream */ public ByteUnPackInputStream(InputStream in) { instream = in; count = rindex = 0; buf = new byte[512]; } /** * Fills the byte buffer by reading data from the stream. * @return the actual number of bytes read, -1 is returned when the end of * stream is reached * @exception IOException If an I/O error has occurred */ public synchronized int fill() throws IOException { int len; len = instream.read(buf, count, (buf.length-count)); count += len; return len; } /** * Fills the byte buffer by reading data from the stream. * @param num the number of bytes to be read * @return the actual number of bytes read, -1 is returned when the end of * stream is reached * @exception IOException If an I/O error has occurred * @exception EOFException If EOF is reached before all "num" bytes are read */ public synchronized int fill( int num ) throws IOException { int len; if ( buf.length < (count+num)) expand(num); len = instream.read(buf, count, num); count += len; return len; } /** * Read a boolean. * @returns the boolean read from the localbuffer * @exception IOException If there is insufficient data in the localbuffer */ public synchronized boolean readBoolean() throws IOException { if ( count < (rindex + 1) ) { throw new IOException("Insufficient Data"); } return ( (getInt() == 0) ? false : true ); } /** * Reads an 8 bit byte. * @returns the byte value read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized byte readByte() throws IOException { if ( count < (rindex + 1) ) { throw new IOException("Insufficient Data"); } return ( buf[rindex++] ); } /** * Reads a 16 bit short. * @returns the 16 bit short read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized short readShort() throws IOException { if ( count < (rindex + 2) ) { throw new IOException("Insufficient Data"); } int msb = getInt(); int lsb = getInt(); return (short)((msb << 8) + (lsb << 0)); } /** * Reads a 16 bit char. * @returns the char read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized char readChar() throws IOException { if ( count < (rindex + 2) ) { throw new IOException("Insufficient Data"); } int msb = getInt(); int lsb = getInt(); return (char)((msb << 8) + (lsb << 0)); } /** * Reads a 32 bit int. * @returns the 32 bit int read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized int readInt() throws IOException { if ( count < (rindex + 4) ) { throw new IOException("Insufficient Data"); } int msba = getInt(); int msbb = getInt(); int lsba = getInt(); int lsbb = getInt(); return ((msba << 24) + (msbb << 16) + (lsba << 8) + (lsbb << 0)); } /** * Reads a 64 bit long. * @returns the 64 bit long read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized long readLong() throws IOException { if ( count < (rindex + 8) ) { throw new IOException("Insufficient Data"); } int msba = getInt(); int msbb = getInt(); int msbc = getInt(); int msbd = getInt(); int lsba = getInt(); int lsbb = getInt(); int lsbc = getInt(); int lsbd = getInt(); return ( (((msba << 24)+(msbb << 16)+(msbc << 8)+(msbd << 0)) << 32L) + (((lsba << 24)+(lsbb << 16)+(lsbc << 8)+(lsbd << 0)) & 0xFFFFFFFFL) ); } /** * Reads a 32 bit float. * @returns the 32 bit float read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized float readFloat() throws IOException { if ( count < (rindex + 4) ) { throw new IOException("Insufficient Data"); } int msba = getInt(); int msbb = getInt(); int lsba = getInt(); int lsbb = getInt(); return ( Float.intBitsToFloat((msba << 24)+ (msbb << 16) +(lsba << 8) + (lsbb << 0))); } /** * Reads a 64 bit double. * @returns the 64 bit double read * @exception IOException If there is insufficient data in the localbuffer */ public synchronized double readDouble() throws IOException { if ( count < (rindex + 8) ) { throw new IOException("Insufficient Data"); } int msba = getInt(); int msbb = getInt(); int msbc = getInt(); int msbd = getInt(); int lsba = getInt(); int lsbb = getInt(); int lsbc = getInt(); int lsbd = getInt(); return ( Double.longBitsToDouble( (((msba << 24)+(msbb << 16)+(msbc << 8)+(msbd << 0)) << 32L) + (((lsba << 24)+(lsbb << 16)+(lsbc << 8)+(lsbd << 0)) & 0xFFFFFFFFL) )); } /** * Reads a String * @returns a read String that has been terminated by a \n, \r, \r\n or EOF * if unterminated it returns all the available. * @exception IOException If there is insufficient data in the localbuffer */ public synchronized String readChars(String s) throws IOException { int len,msb,lsb,lcount; char inchar; if ( (len = count-rindex) <= 2 ) throw new IOException("Insufficient Data"); StringBuffer rstg = new StringBuffer(len); lcount = rindex; loop: while( count-lcount > 1 ) { msb = buf[lcount++]; lsb = buf[lcount++]; inchar = (char)((msb << 8) + (lsb << 0)); switch((msb << 8) + (lsb << 0)) { case -1: case '\n': rstg.append(inchar); break loop; case '\r': if( (count-lcount>1) && (((buf[lcount]<<8)+(buf[lcount+1]<<0)) == '\n') ) { rstg.append("\r\n"); } else { rstg.append("\r"); } break loop; default: rstg.append(inchar); break; } } rindex = lcount; return( rstg.toString()); } /** * Returns the current size of the unread local buffer read from the stream * when fill'd * @returns the size */ public int size() { return (count-rindex); } } /* * End of File: ByteUnPackInputStream.java */