com.phloc.commons.io.streams.NonBlockingByteArrayInputStream Maven / Gradle / Ivy
/**
* Copyright (C) 2006-2015 phloc systems
* http://www.phloc.com
* office[at]phloc[dot]com
*
* 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.
*/
package com.phloc.commons.io.streams;
import java.io.InputStream;
import java.io.Serializable;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.phloc.commons.ValueEnforcer;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
// ESCA-JAVA0143:
/**
* A non-synchronized copy of the class {@link java.io.ByteArrayInputStream}.
*
* @author Philip Helger
* @see java.io.ByteArrayInputStream
*/
public class NonBlockingByteArrayInputStream extends InputStream implements Serializable
{
/**
* An array of bytes that was provided by the creator of the stream. Elements
* buf[0]
through buf[count-1]
are the only bytes
* that can ever be read from the stream; element buf[pos]
is the
* next byte to be read.
*/
protected byte [] m_aBuf;
/**
* The index of the next character to read from the input stream buffer. This
* value should always be nonnegative and not larger than the value of
* count
. The next byte to be read from the input stream buffer
* will be buf[pos]
.
*/
protected int m_nPos;
/**
* The currently marked position in the stream. ByteArrayInputStream objects
* are marked at position zero by default when constructed. They may be marked
* at another position within the buffer by the mark()
method.
* The current buffer position is set to this point by the
* reset()
method.
*
* If no mark has been set, then the value of mark is the offset passed to the
* constructor (or 0 if the offset was not supplied).
*/
protected int m_nMark;
/**
* The index one greater than the last valid character in the input stream
* buffer. This value should always be nonnegative and not larger than the
* length of buf
. It is one greater than the position of the last
* byte within buf
that can ever be read from the input stream
* buffer.
*/
protected int m_nCount;
/**
* Creates a ByteArrayInputStream
so that it uses
* buf
as its buffer array. The buffer array is not copied. The
* initial value of pos
is 0
and the initial value
* of count
is the length of buf
.
*
* @param aBuf
* the input buffer.
*/
@SuppressFBWarnings ({ "EI_EXPOSE_REP2" })
public NonBlockingByteArrayInputStream (@Nonnull final byte [] aBuf)
{
this (aBuf, 0, aBuf.length);
}
/**
* Creates ByteArrayInputStream
that uses aBuf
as
* its buffer array. The initial value of nOfs
is
* offset
and the initial value of m_nCount
is the
* minimum of nOfs+nLen
and aBuf.length
. The buffer
* array is not copied. The buffer's mark is set to the specified offset.
*
* @param aBuf
* the input buffer.
* @param nOfs
* the offset in the buffer of the first byte to read.
* @param nLen
* the maximum number of bytes to read from the buffer.
*/
@SuppressFBWarnings ({ "EI_EXPOSE_REP2" })
public NonBlockingByteArrayInputStream (final byte [] aBuf, final int nOfs, final int nLen)
{
ValueEnforcer.isArrayOfsLen (aBuf, nOfs, nLen);
m_aBuf = aBuf;
m_nPos = nOfs;
m_nCount = Math.min (nOfs + nLen, aBuf.length);
m_nMark = nOfs;
}
/**
* Reads the next byte of data from this input stream. The value byte is
* returned as an int
in the range 0
to
* 255
. If no byte is available because the end of the stream has
* been reached, the value -1
is returned.
*
* This read
method cannot block.
*
* @return the next byte of data, or -1
if the end of the stream
* has been reached.
*/
@Override
public int read ()
{
return m_nPos < m_nCount ? (m_aBuf[m_nPos++] & 0xff) : -1;
}
/**
* Reads up to len
bytes of data into an array of bytes from this
* input stream. If pos
equals count
, then
* -1
is returned to indicate end of file. Otherwise, the number
* k
of bytes read is equal to the smaller of len
* and count-pos
. If k
is positive, then bytes
* buf[pos]
through buf[pos+k-1]
are copied into
* b[off]
through b[off+k-1]
in the manner performed
* by System.arraycopy
. The value k
is added into
* pos
and k
is returned.
*
* This read
method cannot block.
*
* @param aBuf
* the buffer into which the data is read.
* @param nOfs
* the start offset in the destination array b
* @param nLen
* the maximum number of bytes read.
* @return the total number of bytes read into the buffer, or -1
* if there is no more data because the end of the stream has been
* reached.
*/
@Override
public int read (final byte [] aBuf, final int nOfs, final int nLen)
{
ValueEnforcer.isArrayOfsLen (aBuf, nOfs, nLen);
if (m_nPos >= m_nCount)
return -1;
final int nRealLen = m_nPos + nLen > m_nCount ? m_nCount - m_nPos : nLen;
if (nRealLen <= 0)
return 0;
System.arraycopy (m_aBuf, m_nPos, aBuf, nOfs, nRealLen);
m_nPos += nRealLen;
return nRealLen;
}
/**
* Skips n
bytes of input from this input stream. Fewer bytes
* might be skipped if the end of the input stream is reached. The actual
* number k
of bytes to be skipped is equal to the smaller of
* n
and count-pos
. The value k
is
* added into pos
and k
is returned.
*
* @param n
* the number of bytes to be skipped.
* @return the actual number of bytes skipped.
*/
@Override
public long skip (final long n)
{
final long nSkip = m_nPos + n > m_nCount ? m_nCount - m_nPos : n;
if (nSkip <= 0)
return 0;
m_nPos += nSkip;
return nSkip;
}
/**
* Returns the number of remaining bytes that can be read (or skipped over)
* from this input stream.
*
* The value returned is count - pos
, which is the number of
* bytes remaining to be read from the input buffer.
*
* @return the number of remaining bytes that can be read (or skipped over)
* from this input stream without blocking.
*/
@Override
public int available ()
{
return m_nCount - m_nPos;
}
/**
* Tests if this InputStream
supports mark/reset. The
* markSupported
method of ByteArrayInputStream
* always returns true
.
*
* @return Always true
*/
@Override
public boolean markSupported ()
{
return true;
}
/**
* Set the current marked position in the stream. ByteArrayInputStream objects
* are marked at position zero by default when constructed. They may be marked
* at another position within the buffer by this method.
*
* If no mark has been set, then the value of the mark is the offset passed to
* the constructor (or 0 if the offset was not supplied).
*
* Note: The readAheadLimit
for this class has no meaning.
*/
@SuppressWarnings ("sync-override")
@Override
public void mark (final int readAheadLimit)
{
m_nMark = m_nPos;
}
/**
* Resets the buffer to the marked position. The marked position is 0 unless
* another position was marked or an offset was specified in the constructor.
*/
@SuppressWarnings ("sync-override")
@Override
public void reset ()
{
m_nPos = m_nMark;
}
/**
* Closing a ByteArrayInputStream has no effect. The methods in this
* class can be called after the stream has been closed without generating an
* IOException.
*/
@Override
public void close ()
{}
/**
* @return The position where we are in the stream.
*/
@Nonnegative
public int getPosition ()
{
return m_nPos;
}
}