com.threerings.io
Class FramedInputStream

java.lang.Object
  extended by java.io.InputStream
      extended by com.threerings.io.FramedInputStream
All Implemented Interfaces:
Closeable

public class FramedInputStream
extends InputStream

The framed input stream reads input that was framed by a framing output stream. Framing in this case simply means writing the length of the frame followed by the data associated with the frame so that an entire frame can be loaded from the network layer before any higher layer attempts to process it. Additionally, any failure in decoding a frame won't result in the entire stream being skewed due to the remainder of the undecoded frame remaining in the input stream.

The framed input stream reads an entire frame worth of data into its internal buffer when readFrame() is called. It then behaves as if this is the only data available on the stream (meaning that when the data in the frame is exhausted, it will behave as if the end of the stream has been reached). The buffer can only contain a single frame at a time, so any data left over from a previous frame will disappear when readFrame() is called again.

Note: The framing input stream does not synchronize reads from its internal buffer. It is intended to only be accessed from a single thread.

Implementation note: maybe this should derive from FilterInputStream and be tied to a single InputStream for its lifetime.


Field Summary
protected  ByteBuffer _buffer
          The buffer in which we maintain our frame data.
protected  int _have
          The number of bytes total that we have in our buffer (these bytes may comprise more than one frame.
protected  int _length
          The length of the current frame being read.
protected static int HEADER_SIZE
          The size of the frame header (a 32-bit integer).
protected static int INITIAL_BUFFER_CAPACITY
          The default initial size of the internal buffer.
protected static int MAX_BUFFER_CAPACITY
          No need to get out of hand.
 
Constructor Summary
FramedInputStream()
          Creates a new framed input stream.
 
Method Summary
 int available()
          Returns the number of bytes that can be read from this input stream without blocking.
protected  boolean checkForCompleteFrame()
          Returns true if a complete frame is in the buffer, false otherwise.
protected  int decodeLength()
          Decodes and returns the length of the current frame from the buffer if possible.
 void mark(int readAheadLimit)
          Does nothing, as marking is not supported.
 boolean markSupported()
          Always returns false as framed input streams do not support marking.
 int read()
          Reads the next byte of data from this input stream.
 int read(byte[] b, int off, int len)
          Reads up to len bytes of data into an array of bytes from this input stream.
 boolean readFrame(ReadableByteChannel source)
          Reads a frame from the provided channel, appending to any partially read frame.
 void reset()
          Resets the buffer to the beginning of the buffered frames.
 long skip(long n)
          Skips n bytes of input from this input stream.
 
Methods inherited from class java.io.InputStream
close, read
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

_buffer

protected ByteBuffer _buffer
The buffer in which we maintain our frame data.


_length

protected int _length
The length of the current frame being read.


_have

protected int _have
The number of bytes total that we have in our buffer (these bytes may comprise more than one frame.


HEADER_SIZE

protected static final int HEADER_SIZE
The size of the frame header (a 32-bit integer).

See Also:
Constant Field Values

INITIAL_BUFFER_CAPACITY

protected static final int INITIAL_BUFFER_CAPACITY
The default initial size of the internal buffer.

See Also:
Constant Field Values

MAX_BUFFER_CAPACITY

protected static final int MAX_BUFFER_CAPACITY
No need to get out of hand.

See Also:
Constant Field Values
Constructor Detail

FramedInputStream

public FramedInputStream()
Creates a new framed input stream.

Method Detail

readFrame

public boolean readFrame(ReadableByteChannel source)
                  throws IOException
Reads a frame from the provided channel, appending to any partially read frame. If the entire frame data is not yet available, readFrame will return false, otherwise true.

Note: when this method returns true, it is required that the caller read all of the frame data from the stream before again calling readFrame(java.nio.channels.ReadableByteChannel) as the previous frame's data will be elimitated upon the subsequent call.

Returns:
true if the entire frame has been read, false if the buffer contains only a partial frame.
Throws:
IOException

decodeLength

protected final int decodeLength()
Decodes and returns the length of the current frame from the buffer if possible. Returns -1 otherwise.


checkForCompleteFrame

protected final boolean checkForCompleteFrame()
Returns true if a complete frame is in the buffer, false otherwise. If a complete frame is in the buffer, the buffer will be prepared to deliver that frame via our InputStream interface.


read

public int read()
Reads the next byte of data from this input stream. The value byte is returned as an int in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned.

This read method cannot block.

Specified by:
read in class InputStream
Returns:
the next byte of data, or -1 if the end of the stream has been reached.

read

public int read(byte[] b,
                int off,
                int len)
Reads up to len bytes of data into an array of bytes from this input stream. If pos equals count, then -1 is returned to indicate end of file. Otherwise, the number k of bytes read is equal to the smaller of len and count-pos. If k is positive, then bytes buf[pos] through buf[pos+k-1] are copied into b[off] through b[off+k-1] in the manner performed by System.arraycopy. The value k is added into pos and k is returned.

This read method cannot block.

Overrides:
read in class InputStream
Parameters:
b - the buffer into which the data is read.
off - the start offset of the data.
len - the maximum number of bytes read.
Returns:
the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.

skip

public long skip(long n)
Skips n bytes of input from this input stream. Fewer bytes might be skipped if the end of the input stream is reached. The actual number k of bytes to be skipped is equal to the smaller of n and count-pos. The value k is added into pos and k is returned.

Overrides:
skip in class InputStream
Parameters:
n - the number of bytes to be skipped.
Returns:
the actual number of bytes skipped.

available

public int available()
Returns the number of bytes that can be read from this input stream without blocking.

Overrides:
available in class InputStream
Returns:
the number of bytes remaining to be read from the buffered frame.

markSupported

public boolean markSupported()
Always returns false as framed input streams do not support marking.

Overrides:
markSupported in class InputStream

mark

public void mark(int readAheadLimit)
Does nothing, as marking is not supported.

Overrides:
mark in class InputStream

reset

public void reset()
Resets the buffer to the beginning of the buffered frames.

Overrides:
reset in class InputStream