Home | History | Annotate | Download | only in asn1
      1 package org.bouncycastle.asn1;
      2 
      3 import java.io.IOException;
      4 import java.io.OutputStream;
      5 
      6 /**
      7  * Stream that produces output based on the default encoding for the passed in objects.
      8  */
      9 public class ASN1OutputStream
     10 {
     11     private OutputStream os;
     12 
     13     public ASN1OutputStream(
     14         OutputStream    os)
     15     {
     16         this.os = os;
     17     }
     18 
     19     void writeLength(
     20         int length)
     21         throws IOException
     22     {
     23         if (length > 127)
     24         {
     25             int size = 1;
     26             int val = length;
     27 
     28             while ((val >>>= 8) != 0)
     29             {
     30                 size++;
     31             }
     32 
     33             write((byte)(size | 0x80));
     34 
     35             for (int i = (size - 1) * 8; i >= 0; i -= 8)
     36             {
     37                 write((byte)(length >> i));
     38             }
     39         }
     40         else
     41         {
     42             write((byte)length);
     43         }
     44     }
     45 
     46     void write(int b)
     47         throws IOException
     48     {
     49         os.write(b);
     50     }
     51 
     52     void write(byte[] bytes)
     53         throws IOException
     54     {
     55         os.write(bytes);
     56     }
     57 
     58     void write(byte[] bytes, int off, int len)
     59         throws IOException
     60     {
     61         os.write(bytes, off, len);
     62     }
     63 
     64     void writeEncoded(
     65         int     tag,
     66         byte[]  bytes)
     67         throws IOException
     68     {
     69         write(tag);
     70         writeLength(bytes.length);
     71         write(bytes);
     72     }
     73 
     74     void writeTag(int flags, int tagNo)
     75         throws IOException
     76     {
     77         if (tagNo < 31)
     78         {
     79             write(flags | tagNo);
     80         }
     81         else
     82         {
     83             write(flags | 0x1f);
     84             if (tagNo < 128)
     85             {
     86                 write(tagNo);
     87             }
     88             else
     89             {
     90                 byte[] stack = new byte[5];
     91                 int pos = stack.length;
     92 
     93                 stack[--pos] = (byte)(tagNo & 0x7F);
     94 
     95                 do
     96                 {
     97                     tagNo >>= 7;
     98                     stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
     99                 }
    100                 while (tagNo > 127);
    101 
    102                 write(stack, pos, stack.length - pos);
    103             }
    104         }
    105     }
    106 
    107     void writeEncoded(int flags, int tagNo, byte[] bytes)
    108         throws IOException
    109     {
    110         writeTag(flags, tagNo);
    111         writeLength(bytes.length);
    112         write(bytes);
    113     }
    114 
    115     protected void writeNull()
    116         throws IOException
    117     {
    118         os.write(BERTags.NULL);
    119         os.write(0x00);
    120     }
    121 
    122     public void writeObject(
    123         ASN1Encodable obj)
    124         throws IOException
    125     {
    126         if (obj != null)
    127         {
    128             obj.toASN1Primitive().encode(this);
    129         }
    130         else
    131         {
    132             throw new IOException("null object detected");
    133         }
    134     }
    135 
    136     void writeImplicitObject(ASN1Primitive obj)
    137         throws IOException
    138     {
    139         if (obj != null)
    140         {
    141             obj.encode(new ImplicitOutputStream(os));
    142         }
    143         else
    144         {
    145             throw new IOException("null object detected");
    146         }
    147     }
    148 
    149     public void close()
    150         throws IOException
    151     {
    152         os.close();
    153     }
    154 
    155     public void flush()
    156         throws IOException
    157     {
    158         os.flush();
    159     }
    160 
    161     ASN1OutputStream getDERSubStream()
    162     {
    163         return new DEROutputStream(os);
    164     }
    165 
    166     ASN1OutputStream getDLSubStream()
    167     {
    168         return new DLOutputStream(os);
    169     }
    170 
    171     private class ImplicitOutputStream
    172         extends ASN1OutputStream
    173     {
    174         private boolean first = true;
    175 
    176         public ImplicitOutputStream(OutputStream os)
    177         {
    178             super(os);
    179         }
    180 
    181         public void write(int b)
    182             throws IOException
    183         {
    184             if (first)
    185             {
    186                 first = false;
    187             }
    188             else
    189             {
    190                 super.write(b);
    191             }
    192         }
    193     }
    194 }
    195