package aliview.importer;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.apache.log4j.Logger;
public class ByteBufferAutogrow {
private static final Logger logger = Logger.getLogger(ByteBufferAutogrow.class);
private ByteBuffer backend;
private double ALLOCATE_MULTIPLIER = 1.5;
private double ALLOCATE_MULTIPLIER_AFTER_100MB = 1.1;
private double MB = 1000*1000;
private boolean DIRECT_BUFF = false;
public ByteBufferAutogrow(int initialCapacity) {
if(DIRECT_BUFF){
backend = ByteBuffer.allocateDirect(initialCapacity);
}else{
backend = ByteBuffer.allocate(initialCapacity);
}
}
public void append(String more) {
if(more == null || more.length() == 0){
return;
}
byte[] moreBytes = more.getBytes();
// Ensure size
if(backend.remaining() < moreBytes.length){
int exactSize = backend.position() + moreBytes.length;
double multiplier = ALLOCATE_MULTIPLIER;
if(exactSize > 100*MB ){
multiplier = ALLOCATE_MULTIPLIER_AFTER_100MB;
}
int newCapacity = (int) (exactSize * multiplier);
logger.info("newCap=" + newCapacity);
reallocate(newCapacity);
}
backend.put(moreBytes);
}
public void ensureCapacity(int requestCapacity) {
if(requestCapacity > backend.limit()){
reallocate(requestCapacity);
}
}
public void clear(){
backend.clear();
}
/*
*
* method inspired by org.deftserver.io.buffer;
*
*/
// Preserves position.
private void reallocate(int newCapacity) {
// logger.info("reallocate");
int oldPosition = backend.position();
if(backend.hasArray()){
byte[] newBuffer = new byte[newCapacity];
System.arraycopy(backend.array(), 0, newBuffer, 0, backend.position());
backend = ByteBuffer.wrap(newBuffer);
backend.position(oldPosition);
}else{
ByteBuffer newOne = ByteBuffer.allocateDirect(newCapacity);
int endPos = backend.position();
for(int n = 0; n < endPos; n++){
newOne.put(backend.get(n));
}
backend.clear();
backend = newOne;
}
}
public byte[] getBytes(){
if(backend.hasArray()){
return Arrays.copyOfRange(backend.array(), 0, backend.position());
}else{
int length = backend.position();
byte[] retVal = new byte[length];
for(int n = 0; n < retVal.length; n++){
retVal[n] = backend.get(n);
}
return retVal;
}
}
public String toString(){
return new String(getBytes());
}
public int position() {
return backend.position();
}
}