package org.greencheek.util; import java.io.IOException; import java.nio.ByteBuffer; public class ResizeableByteBuffer { // without oops array header is 8 bytes so max array size is that minus public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; private byte[] buf; private volatile int position; private volatile boolean canWrite = true; private final int maxCapacity; public ResizeableByteBuffer(int maxCapacity) { this(4096,maxCapacity); } public ResizeableByteBuffer(int initialCapacity, int maxCapacity) { if(maxCapacity > MAX_ARRAY_SIZE) { maxCapacity = MAX_ARRAY_SIZE; } if(maxCapacity<initialCapacity) { initialCapacity = maxCapacity; } buf = new byte[initialCapacity]; this.maxCapacity = maxCapacity; } public int size() { return position; } public void setSize(int i) { if(i>-1) { this.position = i; } } public void reset() { canWrite = true; position = 0; } public void closeForWrites() { canWrite = false; } public boolean canWrite() { return canWrite; } public byte[] getBuf() { return buf; } public int position() { return position; } public byte[] toByteArray() { final byte[] bytes = new byte[position]; System.arraycopy(buf, 0, bytes, 0, position); return bytes; } public ResizeableByteBuffer trim() { final byte[] bytes = new byte[position]; System.arraycopy(buf, 0, bytes, 0, position); buf = bytes; return this; } public ByteBuffer toByteBuffer() { return ByteBuffer.wrap(buf, 0, position); } public void append(byte b) { if(canWrite && checkSizeAndGrow(1)) { appendNoResize(b); } } public void append(byte[] bytes) { if(canWrite) { int len = bytes.length; if(checkSizeAndGrow(len)) { appendNoResize(bytes, len); } } } public void append(byte[] b, int off, int len) { if(canWrite && checkSizeAndGrow(len)) { System.arraycopy(b, off, buf, position, len); position += len; } } // @Override public void write(byte[] b, int off, int len) throws IOException { append(b,off,len); } // @Override public void write(int b) throws IOException { append((byte)b); } // @Override public void write(byte[] b) { append(b); } private void appendNoResize(byte c) { buf[position++]=c; } private void appendNoResize(byte[] bytes,int len) { System.arraycopy(bytes, 0, buf, position, len); position+=len; } private boolean hasSpace(int extra) { return (extra+position <= buf.length); } private boolean checkSizeAndGrow(int extra) { if(hasSpace(extra)) return true; grow(extra); return canWrite; } private void grow(int extra) { int currentCapacity = buf.length; int requiredCapacity = position+extra; int newSize = currentCapacity*2; if(newSize>=maxCapacity) { newSize = maxCapacity; // new size is less than the required capacity if(newSize<requiredCapacity) { canWrite = false; } } else { if(newSize<requiredCapacity) { newSize = requiredCapacity; } if(requiredCapacity>maxCapacity) { canWrite = false; } } if(canWrite) { byte[] newBuf = new byte[newSize]; System.arraycopy(buf, 0, newBuf, 0, position); buf = newBuf; } } }