Skip to content

Instantly share code, notes, and snippets.

@pingw33n
Created July 12, 2012 15:32
Show Gist options
  • Save pingw33n/3098886 to your computer and use it in GitHub Desktop.
Save pingw33n/3098886 to your computer and use it in GitHub Desktop.
CyclicByteBuffer
import java.io.IOException;
import java.io.InputStream;
import java.nio.BufferOverflowException;
/**
* Cyclic byte array backed buffer that allows independent reads and writes.
*/
public class CyclicByteBuffer
{
public CyclicByteBuffer(int capacity)
{
data = new byte[capacity];
}
public InputStream getInputStream()
{
if (inputStream == null) {
inputStream = new InputStream()
{
@Override
public int read() throws IOException
{
if (byteReadBuf == null) {
byteReadBuf = new byte[1];
}
int r = read(byteReadBuf);
return r != -1 ? byteReadBuf[0] & 0xFF : -1;
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
if (off + len > b.length || off < 0 || len < 0) {
throw new IllegalArgumentException();
}
if (len == 0) {
return 0;
}
int lenAvailable = available();
if (lenAvailable == 0) {
return -1;
}
len = Math.min(len, lenAvailable);
if (wrapBit == 0) {
assert end - start >= len;
System.arraycopy(data, start, b, off, len);
} else {
int leadingChunkLength = data.length - start;
assert leadingChunkLength + end >= len;
System.arraycopy(data, start, b, off, Math.min(leadingChunkLength, len));
if (len > leadingChunkLength) {
System.arraycopy(data, 0, b, off + leadingChunkLength, len - leadingChunkLength);
}
}
free(len);
return len;
}
@Override
public long skip(long n) throws IOException
{
if (n >= Integer.MAX_VALUE) {
n = Integer.MAX_VALUE;
}
n = Math.min(n, length());
free((int) n);
return n;
}
@Override
public int available() throws IOException
{
return length();
}
private byte[] byteReadBuf;
};
}
return inputStream;
}
public int length()
{
int result = end - start + wrapBit * data.length;
assert result >= 0;
return result;
}
public void put(byte[] data, int offset, int length) throws BufferOverflowException
{
if (length > capacityLeft()) {
throw new BufferOverflowException();
}
int leadingChunkLength = Math.min(this.data.length - end, length);
System.arraycopy(data, offset, this.data, end, leadingChunkLength);
end += leadingChunkLength;
assert end <= this.data.length;
if (end == this.data.length) {
end = 0;
wrapBit = 1;
int trailingChunkLength = length - leadingChunkLength;
System.arraycopy(data, offset + leadingChunkLength, this.data, end, trailingChunkLength);
end += trailingChunkLength;
}
}
public void put(byte[] data) throws BufferOverflowException
{
put(data, 0, data.length);
}
public void free(int count)
{
if (count == 0) {
return;
}
if (count <= 0) {
throw new IllegalArgumentException("Negative value of count parameter");
}
if (count > length()) {
throw new IllegalArgumentException("Too much data to free");
}
start += count;
if (start >= data.length) {
start -= data.length;
wrapBit = 0;
}
}
public int capacity()
{
return data.length;
}
public int capacityLeft()
{
return data.length - length();
}
private final byte[] data;
private int start;
private int end;
private int wrapBit;
private InputStream inputStream;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment