/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.io; import java.io.InputStream; import java.util.Iterator; import xxl.core.cursors.Cursor; import xxl.core.cursors.Cursors; import xxl.core.functions.Function; /** * This class delivers an InputStream out of an Iterator which * contains Blocks (created with ObjectToBlockIterator for example). */ public class MultiBlockInputStream extends InputStream { /** Cursor of Blocks */ private Cursor cursor; /** Start offset */ private int startOffset; /** End offset */ private int endOffset; /** The current block which is outputed */ private Block currentBlock; /** Current offset inside the current Block */ private int currentOffset; /** The end offset of the current Block */ private int currentEndOffset; /** * Function which is called to determine the end offset inside the current block. * The function is called with 1 parameter which is the current block. */ Function getLengthUsedInsideBlock; /** * Constructs a new MultiBlockInputStream. An object of this class outputs * parts of the Blocks of an input Iterator as a stream. Each block has an area * which can contain bytes of interest (from startOffset until endOffset). * In addition, for every Block, the Function getLengthUsedInsideBlock is called * (if the Function is not null) to determine the real end of interesting data * inside the Block. For this purpose, the Function Block.GET_REAL_LENGTH can * be useful. * * @param it Input Iterator which contains Block objects. * @param startOffset Beginning offset inside each Block, where the interesting information * starts. * @param endOffset End offset inside each Block, where the interesting information ends. * @param getLengthUsedInsideBlock Function which is called for every Block (if not null) * to determine the real end offset of the current Block. The function gets the * current Block as the only parameter. */ public MultiBlockInputStream (Iterator it, int startOffset, int endOffset, Function getLengthUsedInsideBlock) { this.cursor = Cursors.wrap(it); this.startOffset = startOffset; this.endOffset = endOffset; this.getLengthUsedInsideBlock = getLengthUsedInsideBlock; currentBlock = null; currentOffset = -1; currentEndOffset = -1; if (endOffset <= startOffset) throw new RuntimeException("endOffset has to be larger than startOffset"); } /** * Reads the next byte of the InputStream (-1 if the end of stream is reached). * @return the next byte or -1 if the end of stream is reached. */ public int read() { int nb; if (currentBlock == null) { if (cursor.hasNext()) { currentBlock = (Block) cursor.next(); currentOffset = startOffset; if (getLengthUsedInsideBlock!=null) currentEndOffset = startOffset + ((Integer) getLengthUsedInsideBlock.invoke(currentBlock)).intValue(); else currentEndOffset = endOffset; } else return -1; } nb = currentBlock.get(currentOffset++); if (currentOffset == currentEndOffset) currentBlock = null; // release it as soon as possible if (nb<0) return 256+nb; else return nb; } /** * Closes the InputStream. */ public void close() { } }