Mega Code Archive

 
Categories / Java / File Input Output
 

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)  */ 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 {} }