content: package local.org.bouncycastle.asn1;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  
  import local.org.bouncycastle.util.io.Streams;
  
  
  public abstract class DERGenerator
      extends ASN1Generator
  {       
      private boolean      _tagged = false;
      private boolean      _isExplicit;
      private int          _tagNo;
      
      protected DERGenerator(
          OutputStream out)
      {
          super(out);
      }
  
      public DERGenerator(
          OutputStream out,
          int          tagNo,
          boolean      isExplicit)
      { 
          super(out);
          
          _tagged = true;
          _isExplicit = isExplicit;
          _tagNo = tagNo;
      }
  
      private void writeLength(
          OutputStream out,
          int          length)
          throws IOException
      {
          if (length > 127)
          {
              int size = 1;
              int val = length;
  
              while ((val >>>= 8) != 0)
              {
                  size++;
              }
  
              out.write((byte)(size | 0x80));
  
              for (int i = (size - 1) * 8; i >= 0; i -= 8)
              {
                  out.write((byte)(length >> i));
              }
          }
          else
          {
              out.write((byte)length);
          }
      }
  
      void writeDEREncoded(
          OutputStream out,
          int          tag,
          byte[]       bytes)
          throws IOException
      {
          out.write(tag);
          writeLength(out, bytes.length);
          out.write(bytes);
      }
  
      void writeDEREncoded(
          int       tag,
          byte[]    bytes)
          throws IOException
      {
          if (_tagged)
          {
              int tagNum = _tagNo | BERTags.TAGGED;
              
              if (_isExplicit)
              {
                  int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.TAGGED;
  
                  ByteArrayOutputStream bOut = new ByteArrayOutputStream();
                  
                  writeDEREncoded(bOut, tag, bytes);
                  
                  writeDEREncoded(_out, newTag, bOut.toByteArray());
              }
              else
              {   
                  if ((tag & BERTags.CONSTRUCTED) != 0)
                  {
                      writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes);
                  }
                  else
                  {
                      writeDEREncoded(_out, tagNum, bytes);
                  }
              }
          }
          else
          {
              writeDEREncoded(_out, tag, bytes);
          }
      }
      
      void writeDEREncoded(
          OutputStream out,
          int          tag,
          InputStream  in)
          throws IOException
      {
          writeDEREncoded(out, tag, Streams.readAll(in));
      }
  }
  