All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mediautil.gen.directio.InStreamFromIterativeWriter Maven / Gradle / Ivy

Go to download

SDK for dev_appserver (local development) with some of the dependencies shaded (repackaged)

There is a newer version: 2.0.31
Show newest version
/* MediaUtil LLJTran - $RCSfile: InStreamFromIterativeWriter.java,v $
 * Copyright (C) 1999-2005 Dmitriy Rogatkin, Suresh Mahalingam.  All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *  $Id: InStreamFromIterativeWriter.java,v 1.4 2005/08/18 04:35:34 drogatkin Exp $
 *
 */
package mediautil.gen.directio;

import java.io.*;

/**
 * This class enables reading off directly from an IterativeWriter. The
 * read/skip calls to this class which is to be used as an InputStream translate
 * into nextWrite() calls on the underlying IterativeWriter. Excess bytes
 * written are buffered for the next read call.

* * Another possible use of this class is in converting an IterativeWriter * processing data from an input into a FilterInputStream. * @see IterativeWriter * * @author Suresh Mahalingam ([email protected]) */ public class InStreamFromIterativeWriter extends InputStream { private static byte UNINITIALISED = 0; private static byte OPEN = 1; private static byte CLOSED = 2; /** Internal Byte Queue */ protected byte q[]; /** Internal Byte Queue variables */ protected int qBegin, qEnd, qSize, bufSize, incSize; /** Internal Byte Queue variables */ protected int minWriteSize, writeCushion; private InputStream in; private IterativeWriter writer; private final static int DEF_BUF_SIZE = 4096; private byte oneByteArr[] = new byte[1]; private WriterOutputStream writerStream; private int maxBufSize; private class WriterOutputStream extends OutputStream implements ByteCounter { private byte oneByteArr[] = new byte[1]; public byte requestBuf[]; public int requestPos, requestRemaining; public byte openFlag = UNINITIALISED; private int counterArr[]; private boolean upMode; private long totalBytes = 0; public void setCounter(int counterArr[], boolean upMode) { int i = counterArr[0]; // Good if an exception is detected this.counterArr = counterArr; this.upMode = upMode; } public long getTotalBytes() { return totalBytes; } public void setRequestBuf(byte b[], int off, int len) { requestBuf = b; requestPos = off; requestRemaining = len; } public void write(byte b[], int off, int len) throws IOException { if(openFlag != OPEN) throw new IOException("Stream is not closed or IterativeWriter not set yet"); if(len < 0) throw new IndexOutOfBoundsException("Negative Length Read attempted, len = " + len); byte b1 = b[off], b2 = b[off + len -1]; int lenRequired = len; if(requestRemaining > 0) { int copyLen = len; if(requestRemaining < len) copyLen = requestRemaining; if(requestBuf != null) System.arraycopy(b, off, requestBuf, requestPos, copyLen); requestPos += copyLen; requestRemaining -= copyLen; off += copyLen; len -= copyLen; } if(len > 0) { // q.enqueue(b, off, len); int newQSize = qSize + len; if(newQSize > q.length) reallocBuf(newQSize + incSize - 1 - (newQSize - 1 - bufSize)%incSize); int remain = q.length - qEnd; if(remain > len) remain = len; System.arraycopy(b, off, q, qEnd, remain); off += remain; qEnd += remain; if(qEnd >= q.length) qEnd = 0; remain = len - remain; if(remain > 0) { System.arraycopy(b, off, q, qEnd, remain); qEnd += remain; } qSize = newQSize; } if(lenRequired > 0) { totalBytes += lenRequired; if(counterArr != null) { if(upMode) counterArr[0] += lenRequired; else counterArr[0] -= lenRequired; } } } public void write(int b) throws IOException { oneByteArr[0] = (byte)(b & 255); write(oneByteArr, 0, 1); } public void close() throws IOException { openFlag = CLOSED; } } /** * Creates an InStreamFromIterativeWriter Object. This Object can be used as * an InputStream. However an IterativeWriter must be set before using the * stream. * @param bufSize Buffer Size * @param incSize Bytes by which to increment Buffer Size. Expanding the * buffer will be required when the IterativeWriter's nextWrite method * writes too many bytes beyond the requested size. * @param minWriteSize Minimum Write request size for the IterativeWrite's * nextWrite() call * @param writeCushion Bytes by which the actual bytes written may exceed * the requested number of bytes for the ItertativeWriter's nextWrite() * call. If the nextWrite() call overshoots this limit also then a buffer * expansion may be required which affects performance. */ public InStreamFromIterativeWriter(int bufSize, int incSize, int minWriteSize, int writeCushion) { if(bufSize < 1024) bufSize = 1024; if(incSize < 128) incSize = 128; if(minWriteSize < 256) minWriteSize = 256; if(writeCushion < 256) writeCushion = 256; int minBufSize = minWriteSize + writeCushion + 512; if(bufSize < minBufSize) bufSize = minBufSize; this.bufSize = bufSize; this.incSize = incSize; this.writeCushion = writeCushion; q = new byte[bufSize]; qBegin = 0; qEnd = 0; qSize = 0; maxBufSize = bufSize; } /** * Creates an InStreamFromIterativeWriter Object. This Object can be used as * an InputStream. However an IterativeWriter must be set before using the * stream. Uses a buffer increment size of 512 and minWriteSize and * writeCushion of 750 bytes. * @param bufSize Buffer Size */ public InStreamFromIterativeWriter(int bufSize) { this(bufSize<2048?2048:bufSize, 512, 750, 750); } /** * Creates an InStreamFromIterativeWriter Object. This Object can be used as * an InputStream. However an IterativeWriter must be set before using the * stream. Uses a a buffer size of 4096, buffer increment size of 512 and * minWriteSize and writeCushion of 750 bytes. */ public InStreamFromIterativeWriter() { this(DEF_BUF_SIZE, 1024, 750, 750); } private void reallocBuf(int newLen) { byte newQ[] = new byte[newLen]; int copyLen = q.length - qBegin; if(copyLen > qSize) copyLen = qSize; System.arraycopy(q, qBegin, newQ, 0, copyLen); int pos = copyLen; copyLen = qSize - copyLen; if(copyLen > 0) System.arraycopy(q, 0, newQ, pos, copyLen); q = newQ; qBegin = 0; qEnd = qSize; if(newLen > maxBufSize) maxBufSize = newLen; } /** * Gets the OutputStream for use by the IterativeWriter. * The data written to this stream is buffered for use by this class's * read/skip method. Closing this stream is equivalent to the nextRead of * the iterativeWriter returning IterativeReader.STOP, in which case the * InStreamFromIterativeWriter Object shows end of file after its buffer is * read. * @return Stream for use by IterativeWriter. Note that the returned Object * implements {@link ByteCounter} and can be cast to a ByteCounter for * the IterativeWriter to keep track of the number of bytes written. * @see #setIterativeWriter(IterativeWriter) */ public OutputStream getWriterOutputStream() { if(writerStream == null) writerStream = new WriterOutputStream(); if(writer != null && writerStream.openFlag == UNINITIALISED) writerStream.openFlag = OPEN; return writerStream; } /** * Sets the IterativeWriter for this InStreamFromIterativeWriter. This must * be called before reading data from this stream. * @param iterativeWriter IterativeWriter to call to write data. The * iterativeWriter must write to the OutputStream got by the * getWriterOutputStream() call. * @see #getWriterOutputStream() */ public void setIterativeWriter(IterativeWriter iterativeWriter) { if(iterativeWriter == null) throw new NullPointerException("Writer is null"); if(writerStream != null && writerStream.openFlag == UNINITIALISED) writerStream.openFlag = OPEN; writer = iterativeWriter; } // Skips if b is null, reads otherwise. No validation private int readOrSkip(byte b[], int off, int len) throws IOException { int qReadSize = qSize; int remain; if(qReadSize > len) qReadSize = len; // dequeue(q, b, off, qReadSize) if(qReadSize > 0) { remain = q.length - qBegin; if(remain > qReadSize) remain = qReadSize; if(b != null) { System.arraycopy(q, qBegin, b, off, remain); off += remain; } qBegin += remain; if(qBegin == q.length) qBegin = 0; remain = qReadSize - remain; if(remain > 0) { if(b != null) { System.arraycopy(q, qBegin, b, off, remain); off += remain; } qBegin += remain; } qSize -= qReadSize; if(qSize == 0) { qBegin = 0; qEnd = 0; } } // End dequeue remain = len - qReadSize; if(remain > 0) { // writerStream.setRequestBuf(b, newOff, remain); writerStream.requestBuf = b; writerStream.requestPos = off; writerStream.requestRemaining = remain; int curSize; while(writerStream.openFlag == OPEN && (curSize = bufSize + writerStream.requestRemaining - qSize - writeCushion) > minWriteSize) if(writer.nextWrite(curSize) != IterativeReader.CONTINUE) writerStream.close(); if(q.length > bufSize && q.length - qSize >= incSize) { int resizeLen = bufSize; if(qSize > bufSize) resizeLen = qSize + (incSize - 1 - (qSize - 1 - bufSize)%incSize); reallocBuf(resizeLen); } remain -= writerStream.requestRemaining; } return qReadSize + remain; } /** * Read method of the InStreamFromIterativeWriter. * See the documentation of InputStream.read(..) for more information. This * reads data from an internal buffer calling the iterativeWriter's * nextWrite method to fill the buffer. * @exception IOException If the nextWrite() call of the iterativeWriter * throws an IOException * @see IterativeWriter#nextWrite(int) */ public int read(byte b[], int off, int len) throws IOException { if(len < 0) throw new IndexOutOfBoundsException("Negative Length Read attempted, len = " + len); byte b1 = b[off], b2 = b[off + len -1]; if(len == 0) return 0; int retVal = readOrSkip(b, off, len); if(retVal == 0) retVal = -1; return retVal; } /** * Read method of the InStreamFromIterativeWriter. * See the documentation of InputStream.read(..) for more information. This * reads data from an internal buffer calling the iterativeWriter's * nextWrite method to fill the buffer. * @exception IOException If the nextWrite() call of the iterativeWriter * throws an IOException * @see IterativeWriter#nextWrite(int) */ public int read() throws IOException { int retVal = -1; if(read(oneByteArr, 0, 1) == 1) retVal = oneByteArr[0] & 255; return retVal; } /** * Skip method of the InStreamFromIterativeWriter. * See the documentation of InputStream.skip(..) for more information. This * skips data from an internal buffer calling the iterativeWriter's * nextWrite method to fill the buffer. * @exception IOException If the nextWrite() call of the iterativeWriter * throws an IOException * @see IterativeWriter#nextWrite(int) */ public long skip(long n) throws IOException { long retVal = 0; if(n < 0) n = 0; retVal = readOrSkip(null, 0, (int)n); return retVal; } /** * Available method of the SplitInputStream. * See the documentation of InputStream.available(..) for more information. * This method does not strictly conform to the InputStreams spec since it * always returns atleast 1 unless the IterativeWriter's OutputStream is * closed. */ public int available() throws IOException { // int retVal = q.getQSize(0); int retVal = qSize; if(retVal < 0) retVal = q.length + retVal; if(retVal <= 0) retVal = writerStream.openFlag == OPEN?1:0; return retVal; } /** * Returns the max bufSize. For debugging and informational purposes. * @return Max Buf Size */ public int getMaxBufSize() { return maxBufSize; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy