ByteBuffer.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
phex.io.buffer |
![]() |
![]() |
Phex |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* PHEX - The pure-java Gnutella-servent.
* Copyright (C) 2001 - 2007 Phex Development Group
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* --- SVN Information ---
* $Id: ByteBuffer.java 4115 2008-01-19 12:45:58Z gregork $
*/
package phex.io.buffer;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.CharBuffer;
import java.nio.ReadOnlyBufferException;
import java.nio.ShortBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import phex.utils.HexConverter;
/**
* We use our own ByteBuffer implementations to be able to
* add convenience functionalities.
*
* ByteBuffer allocation is done using heap byte buffers
* since long lasting direct byte buffer with pooling as we
* used before (see DirectByteBuffer and DirectByteBufferProvider)
* turn out to not be a very efficient alternative (in Java 6).
*/
public class ByteBuffer implements Comparable<ByteBuffer>
{
private java.nio.ByteBuffer buf;
protected ByteBuffer( java.nio.ByteBuffer buf )
{
this.buf = buf;
}
/**
* Relative <i>put</i> method for writing a short
* value in little endian byte order.
*
* <p> Writes two bytes containing the given int value, in little
* endian byte order, into this buffer at the current position, and
* increments the position by four. </p>
*
* @param value
* The int value to be written
*
* @return This buffer
*
* @throws BufferOverflowException
* If there are fewer than four bytes
* remaining in this buffer
*
* @throws ReadOnlyBufferException
* If this buffer is read-only
*/
public ByteBuffer putIntLE( int value )
{
put( (byte)(value >> 0) );
put( (byte)(value >> 8) );
put( (byte)(value >> 16) );
put( (byte)(value >> 24) );
return this;
}
/**
* Relative <i>put</i> method for writing a short
* value in little endian byte order.
*
* <p> Writes two bytes containing the given short value, in little
* endian byte order, into this buffer at the current position, and
* increments the position by two. </p>
*
* @param value
* The short value to be written
*
* @return This buffer
*
* @throws BufferOverflowException
* If there are fewer than two bytes
* remaining in this buffer
*
* @throws ReadOnlyBufferException
* If this buffer is read-only
*/
public ByteBuffer putShortLE( short value )
{
put( (byte)(value >> 0) );
put( (byte)(value >> 8) );
return this;
}
/**
* Reads characters from this ByteBuffer, appending it to the given
* StringBuffer, until a '\n' terminated line is read ('\r' is dropped).
* Returns true if a line was read, false if more data needs to be in the
* the buffer until a full line can be read.
*/
public boolean readLine( StringBuilder strBuf )
{
int c = -1; //the character just read
while( hasRemaining() )
{
c = get();
switch(c)
{
// line full
case '\n':
return true;
// drop \r character.
case '\r':
continue;
default:
strBuf.append((char)c);
}
}
return false;
}
/**
* Reads a <code>NUL</code>-terminated string from this buffer using the
* specified <code>decoder</code> and returns it. This method reads
* until the limit of this buffer if no <tt>NUL</tt> is found.
*/
public String getString( CharsetDecoder decoder ) throws CharacterCodingException
{
if( !hasRemaining() )
{
return "";
}
boolean utf16 = decoder.charset().name().startsWith( "UTF-16" );
int oldPos = position();
int oldLimit = limit();
int end = -1;
int newPos;
if( !utf16 )
{
end = indexOf( ( byte ) 0x00 );
if( end < 0 )
{
newPos = end = oldLimit;
}
else
{
newPos = end + 1;
}
}
else
{
int i = oldPos;
for( ;; )
{
boolean wasZero = get( i ) == 0;
i ++;
if( i >= oldLimit )
{
break;
}
if( get( i ) != 0 )
{
i ++;
if( i >= oldLimit )
{
break;
}
else
{
continue;
}
}
if( wasZero )
{
end = i - 1;
break;
}
}
if( end < 0 )
{
newPos = end = oldPos + ( ( oldLimit - oldPos ) & 0xFFFFFFFE );
}
else
{
if( end + 2 <= oldLimit )
{
newPos = end + 2;
}
else
{
newPos = end;
}
}
}
if( oldPos == end )
{
position( newPos );
return "";
}
limit( end );
decoder.reset();
int expectedLength = (int)( remaining() * decoder.averageCharsPerByte() ) + 1;
CharBuffer out = CharBuffer.allocate( expectedLength );
for( ; ; )
{
CoderResult cr;
if( hasRemaining() )
{
cr = decoder.decode( internalBuffer(), out, true );
}
else
{
cr = decoder.flush( out );
}
if( cr.isUnderflow() )
{
break;
}
if( cr.isOverflow() )
{
CharBuffer o = CharBuffer.allocate( out.capacity() + expectedLength );
out.flip();
o.put( out );
out = o;
continue;
}
if( cr.isError() )
{
// Revert the buffer back to the previous state.
limit( oldLimit );
position( oldPos );
cr.throwException();
}
}
limit( oldLimit );
position( newPos );
return out.flip().toString();
}
/**
* Reads a <code>NUL</code>-terminated string from this buffer using the
* specified <code>decoder</code> and returns it.
*
* @param fieldSize the maximum number of bytes to read
*/
public String getString( int fieldSize, CharsetDecoder decoder ) throws CharacterCodingException
{
if( fieldSize < 0 )
{
throw new IllegalArgumentException(
"fieldSize cannot be negative: " + fieldSize );
}
if( fieldSize == 0 )
{
return "";
}
if( !hasRemaining() )
{
return "";
}
boolean utf16 = decoder.charset().name().startsWith( "UTF-16" );
if( utf16 && ( ( fieldSize & 1 ) != 0 ) )
{
throw new IllegalArgumentException( "fieldSize is not even." );
}
int oldPos = position();
int oldLimit = limit();
int end = oldPos + fieldSize;
if( oldLimit < end )
{
throw new BufferUnderflowException();
}
int i;
if( !utf16 )
{
for( i = oldPos; i < end; i ++ )
{
if( get( i ) == 0 )
{
break;
}
}
if( i == end )
{
limit( end );
}
else
{
limit( i );
}
}
else
{
for( i = oldPos; i < end; i += 2 )
{
if( ( get( i ) == 0 ) && ( get( i + 1 ) == 0 ) )
{
break;
}
}
if( i == end )
{
limit( end );
}
else
{
limit( i );
}
}
if( !hasRemaining() )
{
limit( oldLimit );
position( end );
return "";
}
decoder.reset();
int expectedLength = (int)( remaining() * decoder.averageCharsPerByte() ) + 1;
CharBuffer out = CharBuffer.allocate( expectedLength );
for( ; ; )
{
CoderResult cr;
if( hasRemaining() )
{
cr = decoder.decode( internalBuffer(), out, true );
}
else
{
cr = decoder.flush( out );
}
if( cr.isUnderflow() )
{
break;
}
if( cr.isOverflow() )
{
CharBuffer o = CharBuffer.allocate( out.capacity() + expectedLength );
out.flip();
o.put( out );
out = o;
continue;
}
if( cr.isError() )
{
// Revert the buffer back to the previous state.
limit( oldLimit );
position( oldPos );
cr.throwException();
}
}
limit( oldLimit );
position( end );
return out.flip().toString();
}
/**
* Returns the first occurence position of the specified byte from the current position to
* the current limit.
*
* @return <tt>-1</tt> if the specified byte is not found
*/
public int indexOf( byte b )
{
if( hasArray() )
{
int arrayOffset = arrayOffset();
int beginPos = arrayOffset + position();
int limit = arrayOffset + limit();
byte[] array = array();
for( int i = beginPos; i < limit; i ++ )
{
if( array[ i ] == b )
{
return i - arrayOffset;
}
}
}
else
{
int beginPos = position();
int limit = limit();
for( int i = beginPos; i < limit; i ++ )
{
if( get( i ) == b )
{
return i;
}
}
}
return -1;
}
/**
* Forwards the position of this buffer the specified <code>size</code>
* in bytes.
*/
public ByteBuffer skip( int size )
{
return position( position() + size );
}
public java.nio.ByteBuffer internalBuffer()
{
return buf;
}
/**
* Returns a hexdump for this buffer.
*/
public String getHexDump()
{
return this.getHexDump( Integer.MAX_VALUE );
}
/**
* Return a hexdump for this buffer with limited length.
*
* @param lengthLimit The maximum number of bytes to dump from
* the current buffer position.
*/
public String getHexDump( int lengthLimit )
{
return HexConverter.toHexString(this, lengthLimit);
}
@Override
public String toString()
{
StringBuffer sBuf = new StringBuffer();
if( isDirect() )
{
sBuf.append( "DirectBuffer" );
}
else
{
sBuf.append( "HeapBuffer" );
}
sBuf.append( "[pos=" );
sBuf.append( position() );
sBuf.append( " lim=" );
sBuf.append( limit() );
sBuf.append( " cap=" );
sBuf.append( capacity() );
sBuf.append( ": " );
sBuf.append( getHexDump( 16 ) );
sBuf.append( ']' );
return sBuf.toString();
}
@Override
public int hashCode()
{
int h = 1;
int p = position();
for( int i = limit() - 1; i >= p; i -- )
{
h = 31 * h + get( i );
}
return h;
}
@Override
public boolean equals( Object o )
{
if( !( o instanceof ByteBuffer ) )
{
return false;
}
ByteBuffer that = (ByteBuffer)o;
if( this.remaining() != that.remaining() )
{
return false;
}
int p = this.position();
for( int i = this.limit() - 1, j = that.limit() - 1; i >= p; i --, j -- )
{
byte v1 = this.get( i );
byte v2 = that.get( j );
if( v1 != v2 )
{
return false;
}
}
return true;
}
public int compareTo(ByteBuffer that)
{
int n = this.position() + Math.min( this.remaining(), that.remaining() );
for( int i = this.position(), j = that.position(); i < n; i ++, j ++ )
{
byte v1 = this.get( i );
byte v2 = that.get( j );
if( v1 == v2 )
{
continue;
}
if( v1 < v2 )
{
return -1;
}
return +1;
}
return this.remaining() - that.remaining();
}
///////////////////////////////////////////////
// java.nio.ByteBuffer delegation functions //
public byte[] array()
{
return buf.array();
}
public int arrayOffset()
{
return buf.arrayOffset();
}
/**
* @see java.nio.ByteBuffer#asReadOnlyBuffer()
*/
public ByteBuffer asReadOnlyBuffer()
{
return new ByteBuffer( buf.asReadOnlyBuffer() );
}
/**
* @see java.nio.ByteBuffer#asShortBuffer()
*/
public ShortBuffer asShortBuffer()
{
return buf.asShortBuffer();
}
/**
* @see java.nio.ByteBuffer#capacity()
*/
public int capacity()
{
return buf.capacity();
}
/**
* @see java.nio.ByteBuffer#clear()
*/
public ByteBuffer clear()
{
buf.clear();
return this;
}
/**
* @see java.nio.ByteBuffer#compact()
*/
public ByteBuffer compact()
{
buf.compact();
return this;
}
/**
* @see java.nio.ByteBuffer#duplicate()
*/
public ByteBuffer duplicate()
{
return new ByteBuffer( this.buf.duplicate() );
}
/**
* @see java.nio.ByteBuffer#flip()
*/
public ByteBuffer flip()
{
buf.flip();
return this;
}
/**
* @see java.nio.ByteBuffer#get()
*/
public byte get()
{
return buf.get();
}
/**
* @see java.nio.ByteBuffer#get(byte[], int, int)
*/
public ByteBuffer get(byte[] dst, int offset, int length)
{
buf.get( dst, offset, length );
return this;
}
/**
* @see java.nio.ByteBuffer#get(byte[])
*/
public ByteBuffer get(byte[] dst)
{
buf.get( dst );
return this;
}
/**
* @see java.nio.ByteBuffer#get(int)
*/
public byte get(int index)
{
return buf.get( index );
}
public boolean hasArray()
{
return buf.hasArray();
}
public boolean hasRemaining()
{
return buf.hasRemaining();
}
public boolean isDirect()
{
return buf.isDirect();
}
public boolean isReadOnly()
{
return buf.isReadOnly();
}
/**
* @see java.nio.Buffer#limit()
*/
public int limit()
{
return buf.limit();
}
/**
* @see java.nio.Buffer#limit(int)
*/
public ByteBuffer limit( int newLimit)
{
buf.limit( newLimit );
return this;
}
/**
* @see java.nio.Buffer#mark()
*/
public ByteBuffer mark()
{
buf.mark();
return this;
}
/**
* @see java.nio.ByteBuffer#position()
*/
public int position()
{
return buf.position();
}
/**
* @see java.nio.ByteBuffer#position(int)
*/
public ByteBuffer position( int newPosition )
{
buf.position(newPosition);
return this;
}
/**
* @see java.nio.ByteBuffer#put(byte)
*/
public ByteBuffer put(byte b)
{
buf.put( b );
return this;
}
/**
* @see java.nio.ByteBuffer#put(byte[])
*/
public ByteBuffer put( byte[] src )
{
buf.put( src );
return this;
}
/**
* @see java.nio.ByteBuffer#put(byte[], int, int)
*/
public ByteBuffer put(byte[] src, int offset, int length)
{
buf.put( src, offset, length );
return this;
}
public ByteBuffer put(ByteBuffer src)
{
buf.put( src.buf );
return this;
}
public ByteBuffer put(int index, byte b)
{
buf.put( index, b );
return this;
}
/**
* @see java.nio.ByteBuffer#remaining()
*/
public int remaining()
{
return buf.remaining();
}
/**
* @see java.nio.ByteBuffer#reset()
*/
public ByteBuffer reset()
{
buf.reset();
return this;
}
/**
* @see java.nio.ByteBuffer#rewind()
*/
public ByteBuffer rewind()
{
buf.rewind();
return this;
}
/**
* @see java.nio.ByteBuffer#slice()
*/
public ByteBuffer slice()
{
return new ByteBuffer( this.buf.slice() );
}
///////////////////////////////////////////////
// ByteBuffer allocation functions //
/**
* Returns a heap buffer which is capable to hold the specified size.
* @param capacity the capacity of the buffer
*/
public static ByteBuffer allocate( int capacity )
{
java.nio.ByteBuffer nioBuffer = java.nio.ByteBuffer.allocate( capacity );
return new ByteBuffer( nioBuffer );
}
/**
* Wraps the specified byte array into a ByteBuffer.
*/
public static ByteBuffer wrap( byte[] byteArray )
{
return wrap( java.nio.ByteBuffer.wrap( byteArray ) );
}
/**
* Wraps the specified byte array into a ByteBuffer.
*/
public static ByteBuffer wrap( byte[] byteArray, int offset, int length )
{
return wrap( java.nio.ByteBuffer.wrap( byteArray, offset, length ) );
}
/**
* Wraps the specified NIO {@link java.nio.ByteBuffer} into a ByteBuffer.
*/
public static ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
{
return new ByteBuffer( nioBuffer );
}
}
The table below shows all metrics for ByteBuffer.java.




