1package org.bouncycastle.asn1;
2
3import java.io.EOFException;
4import java.io.IOException;
5import java.io.InputStream;
6
7import org.bouncycastle.util.io.Streams;
8
9class DefiniteLengthInputStream
10        extends LimitedInputStream
11{
12    private static final byte[] EMPTY_BYTES = new byte[0];
13
14    private final int _originalLength;
15    private int _remaining;
16
17    DefiniteLengthInputStream(
18        InputStream in,
19        int         length)
20    {
21        super(in, length);
22
23        if (length < 0)
24        {
25            throw new IllegalArgumentException("negative lengths not allowed");
26        }
27
28        this._originalLength = length;
29        this._remaining = length;
30
31        if (length == 0)
32        {
33            setParentEofDetect(true);
34        }
35    }
36
37    int getRemaining()
38    {
39        return _remaining;
40    }
41
42    public int read()
43        throws IOException
44    {
45        if (_remaining == 0)
46        {
47            return -1;
48        }
49
50        int b = _in.read();
51
52        if (b < 0)
53        {
54            throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
55        }
56
57        if (--_remaining == 0)
58        {
59            setParentEofDetect(true);
60        }
61
62        return b;
63    }
64
65    public int read(byte[] buf, int off, int len)
66        throws IOException
67    {
68        if (_remaining == 0)
69        {
70            return -1;
71        }
72
73        int toRead = Math.min(len, _remaining);
74        int numRead = _in.read(buf, off, toRead);
75
76        if (numRead < 0)
77        {
78            throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
79        }
80
81        if ((_remaining -= numRead) == 0)
82        {
83            setParentEofDetect(true);
84        }
85
86        return numRead;
87    }
88
89    byte[] toByteArray()
90        throws IOException
91    {
92        if (_remaining == 0)
93        {
94            return EMPTY_BYTES;
95        }
96
97        byte[] bytes = new byte[_remaining];
98        if ((_remaining -= Streams.readFully(_in, bytes)) != 0)
99        {
100            throw new EOFException("DEF length " + _originalLength + " object truncated by " + _remaining);
101        }
102        setParentEofDetect(true);
103        return bytes;
104    }
105}
106