package se.nicklasgavelin.util;
/**
* A byte array buffer that stores bytes and gives the ability to append new
* bytes easily. Based upon the Apache library ByteArrayBuffer.
*
* @author Nicklas Gavelin, nicklas.gavelin@gmail.com, LuleƄ University of
* Technology
*/
public class ByteArrayBuffer
{
private byte[] buffer;
private int length;
/**
* Create a byte array buffer with a given capacity.
* The buffer will NOT be able to go above the given capacity
*
* @param capacity The capacity of the buffer
*/
public ByteArrayBuffer( int capacity )
{
if( capacity == 0 )
throw new IllegalCapacityException();
this.buffer = new byte[ capacity ];
this.length = 0;
}
/**
* Append a single byte to the end of the buffer
*
* @param b The byte to append
*/
public ByteArrayBuffer append( int b )
{
this.append( (byte) b );
return this;
}
/**
* Append a byte array to the buffer
*
* @param b The byte array to append
*/
public ByteArrayBuffer append( byte[] b )
{
for( int i = 0; i < b.length; i++ )
this.append( b[i] );
return this;
}
/**
* Append a single byte to the buffer
*
* @param b The byte to append
*/
public ByteArrayBuffer append( byte b )
{
// Check if we have any more space to use
if( this.length < this.buffer.length )
this.buffer[this.length++] = b;
return this;
}
/**
* Appends length bytes to this buffer from the given source array starting
* at index offset.
*
* @param b The byte array to append
* @param offset The offset to start from
* @param length The length to append
*/
public ByteArrayBuffer append( byte[] b, int offset, int length )
{
for( int i = offset; i < ( length + offset ); i++ )
this.append( b[i] );
return this;
}
/**
* Returns the reference to the underlying byte array
*/
public byte[] buffer()
{
return this.buffer;
}
/**
* Returns the converted buffer as a byte array
*/
public byte[] toByteArray()
{
// Create a new byte array with our current length
byte[] ret = new byte[ this.length ];
// Copy our values to our new correctly sized array
System.arraycopy( this.buffer, 0, ret, 0, this.length );
// Return the newly created array
return ret;
}
/**
* Clear the data in the buffer,
* will only set the length to 0
*/
public ByteArrayBuffer clear()
{
this.length = 0;
return this;
}
/**
* Returns the byte located at a specific index
*
* @param index The index to return
*
* @return The byte at the given index (null if the index is outside the
* available range)
*/
public byte byteAt( int index )
{
return( index < this.length ? this.buffer[index] : null );
}
/**
* Returns a clone of the current buffer
*
* @return A clone of the current buffer
*/
@Override
public ByteArrayBuffer clone()
{
// Create a buffer with the same capacity
ByteArrayBuffer clone = new ByteArrayBuffer( this.buffer.length );
// Copy our current data
clone.append( this.toByteArray() );
// Return the clone
return clone;
}
/**
* Returns a specific part of the byte array.
* Will throw an IndexOutOfBoundException if the offset + length is larger
* than the capacity of the buffer
*
* @param offset The offset to start at
* @param length The length of the resulted array
*/
public byte[] toByteArray( int offset, int length )
{
byte[] ret = new byte[ length ];
System.arraycopy( this.buffer, offset, ret, 0, length );
return ret;
}
/**
* Returns the index of the first occurrence of byte b
*
* @param b The byte to check index for
*
* @return Returns the index of the given byte or -1 if the byte isn't in
* the buffer
*/
public int indexOf( byte b )
{
// Go through all bytes
for( int i = 0; i < this.length; i++ )
if( this.buffer[i] == b )
return i;
return -1;
}
/**
* Returns true if the buffer is empty, that is if the length is 0
*
* @return True if empty, false otherwise
*/
public boolean isEmpty()
{
return( this.length == 0 );
}
public boolean isFull()
{
return( this.length == this.buffer.length );
}
/**
* Set the new capacity of the byte array,
* will keep the current data as long as the new length is larger
* than the current one.
*
* If the new capacity is smaller than the current capacity and the currently
* stored data exceeds the new capacity length the excessive data will be dropped.
*
* @param capacity The new capacity (may be larger or smaller)
*/
public ByteArrayBuffer setCapacity( int capacity )
{
// Create our new buffer
byte[] newBuffer = new byte[ capacity ];
int newLength = ( this.length > newBuffer.length ? newBuffer.length : this.length );
// Copy our old data to our new buffer
System.arraycopy( this.buffer, 0, newBuffer, 0, newLength );
// Check if we need to remove data
this.length = newLength;
// Replace our old buffer with our new one
this.buffer = newBuffer;
return this;
}
/**
* Returns the total capacity available for storage
*/
public int capacity()
{
return this.buffer.length;
}
/**
* Returns the current amount of data in the array
*
* @return The current amount of bytes
*/
public int size()
{
return this.length;
}
/**
* Returns the current amount of data in the array
*
* @return The current amount of bytes
*/
public int length()
{
return this.length;
}
@Override
public String toString()
{
String s = "";
if( this.length() == 0 )
return s;
for( int i = 0; i < this.length(); i++ )
s += this.buffer[i] + " ";
return s.substring( 0, s.length() - 1 );
}
}