Fast Multi ByteArrayInputStream
/*
* @(#)$Id: codetemplate_xbird.xml 943 2006-09-13 07:03:37Z yui $
*
* Copyright 2006-2008 Makoto YUI
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Makoto YUI - initial implementation
*/
//package xbird.util.io;
import java.io.IOException;
import java.io.InputStream;
/**
*
* <DIV lang="en"></DIV>
* <DIV lang="ja"></DIV>
*
* @author Makoto YUI ([email protected] )
*/
public final class FastMultiByteArrayInputStream extends InputStream {
private final byte [][] _buffers;
private final int _blocksize;
private int _pos;
private int _count;
private byte [] _curBlock;
private int _curBlockIdx;
private int _curBlockOffset;
private boolean _cleanable = false ;
// TODO variable block size
public FastMultiByteArrayInputStream ( byte [][] buffers, int blockSize, int totalSize ) {
if ( buffers == null ) {
throw new IllegalArgumentException () ;
}
this ._buffers = buffers;
this ._blocksize = blockSize;
this ._pos = 0 ;
this ._count = totalSize;
this ._curBlock = buffers [ 0 ] ;
this ._curBlockIdx = 0 ;
this ._curBlockOffset = 0 ;
}
public void setCleanable ( boolean cleanable ) {
this ._cleanable = cleanable;
}
public int read () {
final byte [] block = getCurBlock ( _pos++ ) ;
return ( _pos < _count ) ? ( block [ _curBlockOffset++ ] & 0xff ) : - 1 ;
}
@Override
public int read ( final byte b [] , int off, int len ) {
if ( b == null ) {
throw new NullPointerException () ;
} else if ( off < 0 || len < 0 || len > b.length - off ) {
throw new IndexOutOfBoundsException () ;
}
if ( _pos >= _count ) {
return - 1 ;
}
if ( _pos + len > _count ) {
len = _count - _pos;
}
if ( len <= 0 ) {
return 0 ;
}
final int limit = _pos + len;
for ( int n = _pos; n < limit; ) {
final byte [] block = getCurBlock ( n ) ;
final int numleft = _blocksize - _curBlockOffset;
final int copylen = Math.min ( limit - n, numleft ) ;
System.arraycopy ( block, _curBlockOffset, b, off, copylen ) ;
_curBlockOffset += copylen;
off += copylen;
n += copylen;
}
_pos += len;
return len;
}
private byte [] getCurBlock ( final int pos ) {
if ( _curBlockOffset < _blocksize ) {
return _curBlock;
} else {
if ( _cleanable ) {
_buffers [ _curBlockIdx ] = null ;
}
final int nextBlockIdx = ++_curBlockIdx;
final byte [] block = _buffers [ nextBlockIdx ] ;
this ._curBlock = block;
this ._curBlockOffset = 0 ;
return block;
}
}
@Override
public long skip ( long n ) {
if ( _pos + n > _count ) {
n = _count - _pos;
}
if ( n < 0 ) {
return 0 ;
}
_pos += n;
return n;
}
@Override
public int available () {
return _count - _pos;
}
@Override
public boolean markSupported () {
return false ;
}
@Override
public void mark ( int readAheadLimit ) {
throw new UnsupportedOperationException () ;
}
@Override
public void reset () {
throw new UnsupportedOperationException () ;
}
@Override
public void close () throws IOException {}
}
Related examples in the same category