com.helger.commons.io.stream.NonBlockingByteArrayInputStream Maven / Gradle / Ivy
Show all versions of ph-commons Show documentation
/*
* Copyright (C) 2014-2024 Philip Helger (www.helger.com)
* philip[at]helger[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.helger.commons.io.stream;
import java.io.InputStream;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.collection.ArrayHelper;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* A non-synchronized copy of the class {@link java.io.ByteArrayInputStream}.
*
* @author Philip Helger
* @see java.io.ByteArrayInputStream
*/
public class NonBlockingByteArrayInputStream extends InputStream
{
public static final boolean DEFAULT_COPY_NEEDED = false;
/**
* 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.
* NonBlockingByteArrayInputStream 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;
private final boolean m_bIsCopy;
/**
* Creates a NonBlockingByteArrayInputStream
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.
*/
public NonBlockingByteArrayInputStream (@Nonnull final byte [] aBuf)
{
this (aBuf, 0, aBuf.length, DEFAULT_COPY_NEEDED);
}
/**
* Creates a NonBlockingByteArrayInputStream
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.
* @param bIsCopyNeeded
* true
if the array should be copied, false
* if not.
*/
public NonBlockingByteArrayInputStream (@Nonnull final byte [] aBuf, final boolean bIsCopyNeeded)
{
this (aBuf, 0, aBuf.length, bIsCopyNeeded);
}
/**
* Creates NonBlockingByteArrayInputStream
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.
*/
public NonBlockingByteArrayInputStream (@Nonnull final byte [] aBuf, @Nonnegative final int nOfs, @Nonnegative final int nLen)
{
this (aBuf, nOfs, nLen, DEFAULT_COPY_NEEDED);
}
/**
* Creates NonBlockingByteArrayInputStream
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'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.
* @param bIsCopyNeeded
* true
if the provided byte array needs to be copied,
* false
if not.
*/
@SuppressFBWarnings ({ "EI_EXPOSE_REP2" })
public NonBlockingByteArrayInputStream (@Nonnull final byte [] aBuf,
@Nonnegative final int nOfs,
@Nonnegative final int nLen,
final boolean bIsCopyNeeded)
{
ValueEnforcer.isArrayOfsLen (aBuf, nOfs, nLen);
m_aBuf = bIsCopyNeeded ? ArrayHelper.getCopy (aBuf, nOfs, nLen) : aBuf;
m_nPos = bIsCopyNeeded ? 0 : nOfs;
m_nCount = bIsCopyNeeded ? nLen : Math.min (nOfs + nLen, aBuf.length);
m_nMark = m_nPos;
m_bIsCopy = bIsCopyNeeded;
}
public final boolean isCopy ()
{
return m_bIsCopy;
}
/**
* 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 ()
{
if (m_nPos >= m_nCount)
return -1;
final int ret = m_aBuf[m_nPos] & 0xff;
m_nPos++;
return ret;
}
/**
* 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 += (int) 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
* NonBlockingByteArrayInputStream
always returns
* true
.
*
* @return Always true
*/
@Override
public boolean markSupported ()
{
return true;
}
/**
* Set the current marked position in the stream.
* NonBlockingByteArrayInputStream 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 NonBlockingByteArrayInputStream
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;
}
}