001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.EOFException;
004import java.io.IOException;
005import java.io.InputStream;
006
007import org.bouncycastle.util.io.Streams;
008
009class DefiniteLengthInputStream
010        extends LimitedInputStream
011{
012    private static final byte[] EMPTY_BYTES = new byte[0];
013
014    private final int _originalLength;
015    private int _remaining;
016
017    DefiniteLengthInputStream(
018        InputStream in,
019        int         length)
020    {
021        super(in, length);
022
023        if (length < 0)
024        {
025            throw new IllegalArgumentException("negative lengths not allowed");
026        }
027
028        this._originalLength = length;
029        this._remaining = length;
030
031        if (length == 0)
032        {
033            setParentEofDetect(true);
034        }
035    }
036
037    int getRemaining()
038    {
039        return _remaining;
040    }
041
042    public int read()
043        throws IOException
044    {
045        if (_remaining == 0)
046        {
047            return -1;
048        }
049
050        int b = _in.read();
051
052        if (b < 0)
053        {
054            throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
055        }
056
057        if (--_remaining == 0)
058        {
059            setParentEofDetect(true);
060        }
061
062        return b;
063    }
064
065    public int read(byte[] buf, int off, int len)
066        throws IOException
067    {
068        if (_remaining == 0)
069        {
070            return -1;
071        }
072
073        int toRead = Math.min(len, _remaining);
074        int numRead = _in.read(buf, off, toRead);
075
076        if (numRead < 0)
077        {
078            throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
079        }
080
081        if ((_remaining -= numRead) == 0)
082        {
083            setParentEofDetect(true);
084        }
085
086        return numRead;
087    }
088
089    byte[] toByteArray()
090        throws IOException
091    {
092        if (_remaining == 0)
093        {
094            return EMPTY_BYTES;
095        }
096
097        byte[] bytes = new byte[_remaining];
098        if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
099        {
100            throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
101        }
102        setParentEofDetect(true);
103        return bytes;
104    }
105}