1 package org.bouncycastle.asn1;
2 
3 import java.io.IOException;
4 import java.io.InputStream;
5 
6 class ConstructedOctetStream
7     extends InputStream
8 {
9     private final ASN1StreamParser _parser;
10 
11     private boolean                _first = true;
12     private InputStream            _currentStream;
13 
ConstructedOctetStream( ASN1StreamParser parser)14     ConstructedOctetStream(
15         ASN1StreamParser parser)
16     {
17         _parser = parser;
18     }
19 
read(byte[] b, int off, int len)20     public int read(byte[] b, int off, int len) throws IOException
21     {
22         if (_currentStream == null)
23         {
24             if (!_first)
25             {
26                 return -1;
27             }
28 
29             ASN1OctetStringParser next = getNextParser();
30             if (next == null)
31             {
32                 return -1;
33             }
34 
35             _first = false;
36             _currentStream = next.getOctetStream();
37         }
38 
39         int totalRead = 0;
40 
41         for (;;)
42         {
43             int numRead = _currentStream.read(b, off + totalRead, len - totalRead);
44 
45             if (numRead >= 0)
46             {
47                 totalRead += numRead;
48 
49                 if (totalRead == len)
50                 {
51                     return totalRead;
52                 }
53             }
54             else
55             {
56                 ASN1OctetStringParser next = getNextParser();
57                 if (next == null)
58                 {
59                     _currentStream = null;
60                     return totalRead < 1 ? -1 : totalRead;
61                 }
62 
63                 _currentStream = next.getOctetStream();
64             }
65         }
66     }
67 
read()68     public int read()
69         throws IOException
70     {
71         if (_currentStream == null)
72         {
73             if (!_first)
74             {
75                 return -1;
76             }
77 
78             ASN1OctetStringParser next = getNextParser();
79             if (next == null)
80             {
81                 return -1;
82             }
83 
84             _first = false;
85             _currentStream = next.getOctetStream();
86         }
87 
88         for (;;)
89         {
90             int b = _currentStream.read();
91 
92             if (b >= 0)
93             {
94                 return b;
95             }
96 
97             ASN1OctetStringParser next = getNextParser();
98             if (next == null)
99             {
100                 _currentStream = null;
101                 return -1;
102             }
103 
104             _currentStream = next.getOctetStream();
105         }
106     }
107 
getNextParser()108     private ASN1OctetStringParser getNextParser() throws IOException
109     {
110         ASN1Encodable asn1Obj = _parser.readObject();
111         if (asn1Obj == null)
112         {
113             return null;
114         }
115 
116         if (asn1Obj instanceof ASN1OctetStringParser)
117         {
118             return (ASN1OctetStringParser)asn1Obj;
119         }
120 
121         throw new IOException("unknown object encountered: " + asn1Obj.getClass());
122     }
123 }
124