package org.bouncycastle.asn1;

import org.bouncycastle.util.io.Streams;

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

class DefiniteLengthInputStream
        extends LimitedInputStream
{
    private static final byte[] EMPTY_BYTES = new byte[0];

    private int _length;

    DefiniteLengthInputStream(
        InputStream in,
        int         length)
    {
        super(in);

        if (length < 0)
        {
            throw new IllegalArgumentException("negative lengths not allowed");
        }

        this._length = length;

        if (length == 0)
        {
            setParentEofDetect(true);
        }
    }

    public int read()
        throws IOException
    {
        if (_length == 0)
        {
            return -1;
        }

        int b = _in.read();

        if (b < 0)
        {
            throw new EOFException();
        }

        if (--_length == 0)
        {
            setParentEofDetect(true);
        }

        return b;
    }

    public int read(byte[] buf, int off, int len)
        throws IOException
    {
        if (_length == 0)
        {
            return -1;
        }

        int toRead = Math.min(len, _length);
        int numRead = _in.read(buf, off, toRead);

        if (numRead < 0)
        {
            throw new EOFException();
        }

        if ((_length -= numRead) == 0)
        {
            setParentEofDetect(true);
        }

        return numRead;
    }

    byte[] toByteArray()
        throws IOException
    {
        if (_length == 0)
        {
            return EMPTY_BYTES;
        }

        byte[] bytes = new byte[_length];
        if (Streams.readFully(_in, bytes) < _length)
        {
            throw new EOFException();
        }
        _length = 0;
        setParentEofDetect(true);
        return bytes;
    }
}

@@ -298,19 +298,61 @@
 ate 
-int _length
+final int _originalLength;%0A    private int _remaining
 ;%0A%0A 
@@ -598,22 +598,64 @@
   this._
-length
+originalLength = length;%0A        this._remaining
  = lengt
@@ -808,38 +808,41 @@
  %7B%0A        if (_
-length
+remaining
  == 0)%0A        %7B
@@ -961,32 +961,102 @@
 ew EOFException(
+%22DEF length %22 + _originalLength + %22 object truncated by %22 + _remaining
 );%0A        %7D%0A%0A  
@@ -1068,22 +1068,25 @@
  if (--_
-length
+remaining
  == 0)%0A 
@@ -1256,38 +1256,41 @@
  %7B%0A        if (_
-length
+remaining
  == 0)%0A        %7B
@@ -1360,22 +1360,25 @@
 n(len, _
-length
+remaining
 );%0A     
@@ -1485,32 +1485,102 @@
 ew EOFException(
+%22DEF length %22 + _originalLength + %22 object truncated by %22 + _remaining
 );%0A        %7D%0A%0A  
@@ -1591,22 +1591,25 @@
   if ((_
-length
+remaining
  -= numR
@@ -1780,22 +1780,25 @@
    if (_
-length
+remaining
  == 0)%0A 
@@ -1882,22 +1882,25 @@
 w byte%5B_
-length
+remaining
 %5D;%0A     
@@ -1906,16 +1906,31 @@
     if (
+(_remaining -= 
 Streams.
@@ -1954,18 +1954,14 @@
 tes)
- %3C _length
+) != 0
 )%0A  
@@ -2007,41 +2007,90 @@
 ion(
-);%0A        %7D%0A        _length = 0;
+%22DEF length %22 + _originalLength + %22 object truncated by %22 + _remaining);%0A        %7D
 %0A   

Improve exception messages