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 (yuin405+xbird@gmail.com) */publicfinalclass FastMultiByteArrayInputStream extends InputStream { privatefinalbyte[][] _buffers; privatefinalint _blocksize; privateint _pos; privateint _count; privatebyte[] _curBlock; privateint _curBlockIdx; privateint _curBlockOffset; privateboolean _cleanable = false; // TODO variable block size public FastMultiByteArrayInputStream(byte[][] buffers, int blockSize, int totalSize) { if(buffers == null) { thrownew IllegalArgumentException(); } this._buffers = buffers; this._blocksize = blockSize; this._pos = 0; this._count = totalSize; this._curBlock = buffers[0]; this._curBlockIdx = 0; this._curBlockOffset = 0; } publicvoid setCleanable(boolean cleanable) { this._cleanable = cleanable; } publicint read() { finalbyte[] block = getCurBlock(_pos++); return (_pos < _count) ? (block[_curBlockOffset++] & 0xff) : -1; } @Override publicint read(finalbyte b[], int off, int len) { if(b == null) { thrownew NullPointerException(); } elseif(off < 0 || len < 0 || len > b.length - off) { thrownew IndexOutOfBoundsException(); } if(_pos >= _count) { return -1; } if(_pos + len > _count) { len = _count - _pos; } if(len <= 0) { return 0; } finalint limit = _pos + len; for(int n = _pos; n < limit;) { finalbyte[] block = getCurBlock(n); finalint numleft = _blocksize - _curBlockOffset; finalint copylen = Math.min(limit - n, numleft); System.arraycopy(block, _curBlockOffset, b, off, copylen); _curBlockOffset += copylen; off += copylen; n += copylen; } _pos += len; return len; } privatebyte[] getCurBlock(finalint pos) { if(_curBlockOffset < _blocksize) { return _curBlock; } else { if(_cleanable) { _buffers[_curBlockIdx] = null; } finalint nextBlockIdx = ++_curBlockIdx; finalbyte[] block = _buffers[nextBlockIdx]; this._curBlock = block; this._curBlockOffset = 0; return block; } } @Override publiclong skip(long n) { if(_pos + n > _count) { n = _count - _pos; } if(n < 0) { return 0; } _pos += n; return n; } @Override publicint available() { return _count - _pos; } @Override publicboolean markSupported() { return false; } @Override publicvoid mark(int readAheadLimit) { thrownew UnsupportedOperationException(); } @Override publicvoid reset() { thrownew UnsupportedOperationException(); } @Override publicvoid close() throws IOException {} }
Related examples in the same category