package org.bouncycastle.asn1;

import java.io.InputStream;
import java.io.IOException;

class ConstructedOctetStream
    extends InputStream
{
    private final ASN1ObjectParser _parser;

    private boolean                _first = true;
    private InputStream            _currentStream;

    ConstructedOctetStream(
        ASN1ObjectParser parser)
    {
        _parser = parser;
    }

    public int read()
        throws IOException
    {
        if (_first)
        {
            ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();

            if (s == null)
            {
                return -1;
            }

            _first = false;
            _currentStream = s.getOctetStream();
        }
        else if (_currentStream == null)
        {
            return -1;
        }

        int b = _currentStream.read();

        if (b < 0)
        {
            ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();

            if (s == null)
            {
                _currentStream = null;

                return -1;
            }

            _currentStream = s.getOctetStream();

            return _currentStream.read();
        }
        else
        {
            return b;
        }
    }
}

@@ -404,25 +404,43 @@
 nt read(
-)%0A       
+byte%5B%5D b, int off, int len)
  throws 
@@ -470,16 +470,67 @@
    if (_
+currentStream == null)%0A        %7B%0A            if (!_
 first)%0A 
@@ -528,33 +528,79 @@
 _first)%0A        
-%7B
+    %7B%0A                return -1;%0A            %7D%0A
 %0A            ASN
@@ -834,32 +834,33 @@
 ;%0A        %7D%0A
+%0A
         
 else if (_cu
@@ -851,51 +851,351 @@
     
-else if (_currentStream == null)%0A        %7B%0A
+for (;;)%0A        %7B%0A            int numRead = _currentStream.read(b, off, len);%0A%0A            if (numRead %3E= 0)%0A            %7B%0A                return numRead;%0A            %7D%0A%0A            ASN1OctetStringParser aos = (ASN1OctetStringParser)_parser.readObject();%0A%0A            if (aos == null)%0A            %7B%0A                _currentStream = null;%0A    
     
@@ -1213,32 +1213,36 @@
 urn -1;%0A        
+    
 %7D%0A%0A        int b
@@ -1240,15 +1240,11 @@
     
-int b =
+   
  _cu
@@ -1258,46 +1258,231 @@
 ream
-.read
+ = aos.getOctetStream
 ();%0A
-%0A        if (b %3C 0)%0A        %7B
+        %7D%0A    %7D%0A%0A    public int read()%0A        throws IOException%0A    %7B%0A        if (_currentStream == null)%0A        %7B%0A            if (!_first)%0A            %7B%0A                return -1;%0A            %7D%0A
 %0A   
@@ -1553,32 +1553,36 @@
 r.readObject();%0A
+    
 %0A            if 
@@ -1623,39 +1623,26 @@
         
-_currentStream = null;%0A
+return -1;
 %0A       
@@ -1642,38 +1642,30 @@
             
+%7D%0A
     
-return -1;
 %0A           
@@ -1657,34 +1657,47 @@
    %0A            
-%7D%0A
+_first = false;
 %0A            _cu
@@ -1726,33 +1726,32 @@
 etStream();%0A
-%0A
         
     return _
@@ -1742,42 +1742,150 @@
     
+%7D%0A%0A
     
-return _currentStream.read();%0A
+    for (;;)%0A        %7B%0A            int b = _currentStream.read();%0A%0A            if (b %3E= 0)%0A            %7B%0A                return b;%0A    
     
@@ -1890,24 +1890,29 @@
       %7D%0A
+%0A    
         
 else%0A   
@@ -1907,21 +1907,117 @@
     
-else%0A
+ASN1OctetStringParser s = (ASN1OctetStringParser)_parser.readObject();%0A%0A            if (s == null)%0A  
         
 %7B%0A  
@@ -2004,32 +2004,34 @@
 null)%0A          
+  
 %7B%0A            re
@@ -2024,32 +2024,140 @@
             
-return b
+    _currentStream = null;%0A                return -1;%0A            %7D%0A%0A            _currentStream = s.getOctetStream()
 ;%0A        %7D%0A

Handle empty "component" streams Implement read(byte[],int,int) as optimisation