001package org.apache.commons.ssl.org.bouncycastle.asn1;
002
003import java.io.ByteArrayInputStream;
004import java.io.FileInputStream;
005import java.io.IOException;
006import java.io.InputStream;
007import java.nio.channels.FileChannel;
008
009class StreamUtil
010{
011    private static final long  MAX_MEMORY = Runtime.getRuntime().maxMemory();
012
013    /**
014     * Find out possible longest length...
015     *
016     * @param in input stream of interest
017     * @return length calculation or MAX_VALUE.
018     */
019    static int findLimit(InputStream in)
020    {
021        if (in instanceof LimitedInputStream)
022        {
023            return ((LimitedInputStream)in).getRemaining();
024        }
025        else if (in instanceof ASN1InputStream)
026        {
027            return ((ASN1InputStream)in).getLimit();
028        }
029        else if (in instanceof ByteArrayInputStream)
030        {
031            return ((ByteArrayInputStream)in).available();
032        }
033        else if (in instanceof FileInputStream)
034        {
035            try
036            {
037                FileChannel channel = ((FileInputStream)in).getChannel();
038                long  size = (channel != null) ? channel.size() : Integer.MAX_VALUE;
039
040                if (size < Integer.MAX_VALUE)
041                {
042                    return (int)size;
043                }
044            }
045            catch (IOException e)
046            {
047                // ignore - they'll find out soon enough!
048            }
049        }
050
051        if (MAX_MEMORY > Integer.MAX_VALUE)
052        {
053            return Integer.MAX_VALUE;
054        }
055
056        return (int)MAX_MEMORY;
057    }
058
059    static int calculateBodyLength(
060        int length)
061    {
062        int count = 1;
063
064        if (length > 127)
065        {
066            int size = 1;
067            int val = length;
068
069            while ((val >>>= 8) != 0)
070            {
071                size++;
072            }
073
074            for (int i = (size - 1) * 8; i >= 0; i -= 8)
075            {
076                count++;
077            }
078        }
079
080        return count;
081    }
082
083    static int calculateTagLength(int tagNo)
084        throws IOException
085    {
086        int length = 1;
087
088        if (tagNo >= 31)
089        {
090            if (tagNo < 128)
091            {
092                length++;
093            }
094            else
095            {
096                byte[] stack = new byte[5];
097                int pos = stack.length;
098
099                stack[--pos] = (byte)(tagNo & 0x7F);
100
101                do
102                {
103                    tagNo >>= 7;
104                    stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
105                }
106                while (tagNo > 127);
107
108                length += stack.length - pos;
109            }
110        }
111
112        return length;
113    }
114}