1package org.bouncycastle.asn1;
2
3import java.io.EOFException;
4import java.io.IOException;
5import java.io.InputStream;
6
7class IndefiniteLengthInputStream
8    extends LimitedInputStream
9{
10    private int _b1;
11    private int _b2;
12    private boolean _eofReached = false;
13    private boolean _eofOn00 = true;
14
15    IndefiniteLengthInputStream(
16        InputStream in,
17        int         limit)
18        throws IOException
19    {
20        super(in, limit);
21
22        _b1 = in.read();
23        _b2 = in.read();
24
25        if (_b2 < 0)
26        {
27            // Corrupted stream
28            throw new EOFException();
29        }
30
31        checkForEof();
32    }
33
34    void setEofOn00(
35        boolean eofOn00)
36    {
37        _eofOn00 = eofOn00;
38        checkForEof();
39    }
40
41    private boolean checkForEof()
42    {
43        if (!_eofReached && _eofOn00 && (_b1 == 0x00 && _b2 == 0x00))
44        {
45            _eofReached = true;
46            setParentEofDetect(true);
47        }
48        return _eofReached;
49    }
50
51    public int read(byte[] b, int off, int len)
52        throws IOException
53    {
54        // Only use this optimisation if we aren't checking for 00
55        if (_eofOn00 || len < 3)
56        {
57            return super.read(b, off, len);
58        }
59
60        if (_eofReached)
61        {
62            return -1;
63        }
64
65        int numRead = _in.read(b, off + 2, len - 2);
66
67        if (numRead < 0)
68        {
69            // Corrupted stream
70            throw new EOFException();
71        }
72
73        b[off] = (byte)_b1;
74        b[off + 1] = (byte)_b2;
75
76        _b1 = _in.read();
77        _b2 = _in.read();
78
79        if (_b2 < 0)
80        {
81            // Corrupted stream
82            throw new EOFException();
83        }
84
85        return numRead + 2;
86    }
87
88    public int read()
89        throws IOException
90    {
91        if (checkForEof())
92        {
93            return -1;
94        }
95
96        int b = _in.read();
97
98        if (b < 0)
99        {
100            // Corrupted stream
101            throw new EOFException();
102        }
103
104        int v = _b1;
105
106        _b1 = _b2;
107        _b2 = b;
108
109        return v;
110    }
111}
112