content: package local.org.bouncycastle.asn1;
  
  import java.io.IOException;
  import java.io.OutputStream;
  
  /**
   * Stream that produces output based on the default encoding for the passed in objects.
   */
  public class ASN1OutputStream
  {
      private OutputStream os;
  
      public ASN1OutputStream(
          OutputStream    os)
      {
          this.os = os;
      }
  
      void writeLength(
          int length)
          throws IOException
      {
          if (length > 127)
          {
              int size = 1;
              int val = length;
  
              while ((val >>>= 8) != 0)
              {
                  size++;
              }
  
              write((byte)(size | 0x80));
  
              for (int i = (size - 1) * 8; i >= 0; i -= 8)
              {
                  write((byte)(length >> i));
              }
          }
          else
          {
              write((byte)length);
          }
      }
  
      void write(int b)
          throws IOException
      {
          os.write(b);
      }
  
      void write(byte[] bytes)
          throws IOException
      {
          os.write(bytes);
      }
  
      void write(byte[] bytes, int off, int len)
          throws IOException
      {
          os.write(bytes, off, len);
      }
  
      void writeEncoded(
          int     tag,
          byte[]  bytes)
          throws IOException
      {
          write(tag);
          writeLength(bytes.length);
          write(bytes);
      }
  
      void writeTag(int flags, int tagNo)
          throws IOException
      {
          if (tagNo < 31)
          {
              write(flags | tagNo);
          }
          else
          {
              write(flags | 0x1f);
              if (tagNo < 128)
              {
                  write(tagNo);
              }
              else
              {
                  byte[] stack = new byte[5];
                  int pos = stack.length;
  
                  stack[--pos] = (byte)(tagNo & 0x7F);
  
                  do
                  {
                      tagNo >>= 7;
                      stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
                  }
                  while (tagNo > 127);
  
                  write(stack, pos, stack.length - pos);
              }
          }
      }
  
      void writeEncoded(int flags, int tagNo, byte[] bytes)
          throws IOException
      {
          writeTag(flags, tagNo);
          writeLength(bytes.length);
          write(bytes);
      }
  
      protected void writeNull()
          throws IOException
      {
          os.write(BERTags.NULL);
          os.write(0x00);
      }
  
      public void writeObject(
          ASN1Encodable obj)
          throws IOException
      {
          if (obj != null)
          {
              obj.toASN1Primitive().encode(this);
          }
          else
          {
              throw new IOException("null object detected");
          }
      }
  
      void writeImplicitObject(ASN1Primitive obj)
          throws IOException
      {
          if (obj != null)
          {
              obj.encode(new ImplicitOutputStream(os));
          }
          else
          {
              throw new IOException("null object detected");
          }
      }
  
      public void close()
          throws IOException
      {
          os.close();
      }
  
      public void flush()
          throws IOException
      {
          os.flush();
      }
  
      ASN1OutputStream getDERSubStream()
      {
          return new DEROutputStream(os);
      }
  
      ASN1OutputStream getDLSubStream()
      {
          return new DLOutputStream(os);
      }
  
      private class ImplicitOutputStream
          extends ASN1OutputStream
      {
          private boolean first = true;
  
          public ImplicitOutputStream(OutputStream os)
          {
              super(os);
          }
  
          public void write(int b)
              throws IOException
          {
              if (first)
              {
                  first = false;
              }
              else
              {
                  super.write(b);
              }
          }
      }
  }
  