// 
// Decompiled by Procyon v0.6.0
// 

package org.bouncycastle.asn1;

import java.io.IOException;
import java.io.OutputStream;

public class ASN1OutputStream
{
    private OutputStream os;
    
    public static ASN1OutputStream create(final OutputStream outputStream) {
        return new ASN1OutputStream(outputStream);
    }
    
    public static ASN1OutputStream create(final OutputStream outputStream, final String s) {
        if (s.equals("DER")) {
            return new DEROutputStream(outputStream);
        }
        if (s.equals("DL")) {
            return new DLOutputStream(outputStream);
        }
        return new ASN1OutputStream(outputStream);
    }
    
    ASN1OutputStream(final OutputStream os) {
        this.os = os;
    }
    
    public void close() throws IOException {
        this.os.close();
    }
    
    public void flush() throws IOException {
        this.os.flush();
    }
    
    public final void writeObject(final ASN1Encodable asn1Encodable) throws IOException {
        if (null == asn1Encodable) {
            throw new IOException("null object detected");
        }
        this.writePrimitive(asn1Encodable.toASN1Primitive(), true);
        this.flushInternal();
    }
    
    public final void writeObject(final ASN1Primitive asn1Primitive) throws IOException {
        if (null == asn1Primitive) {
            throw new IOException("null object detected");
        }
        this.writePrimitive(asn1Primitive, true);
        this.flushInternal();
    }
    
    void flushInternal() throws IOException {
    }
    
    DEROutputStream getDERSubStream() {
        return new DEROutputStream(this.os);
    }
    
    DLOutputStream getDLSubStream() {
        return new DLOutputStream(this.os);
    }
    
    final void writeDL(int i) throws IOException {
        if (i < 128) {
            this.write(i);
        }
        else {
            final byte[] array = new byte[5];
            int length = array.length;
            do {
                array[--length] = (byte)i;
                i >>>= 8;
            } while (i != 0);
            final int n = array.length - length;
            array[--length] = (byte)(0x80 | n);
            this.write(array, length, n + 1);
        }
    }
    
    final void write(final int n) throws IOException {
        this.os.write(n);
    }
    
    final void write(final byte[] b, final int off, final int len) throws IOException {
        this.os.write(b, off, len);
    }
    
    void writeElements(final ASN1Encodable[] array) throws IOException {
        for (int i = 0; i < array.length; ++i) {
            array[i].toASN1Primitive().encode(this, true);
        }
    }
    
    final void writeEncodingDL(final boolean b, final int n, final byte b2) throws IOException {
        this.writeIdentifier(b, n);
        this.writeDL(1);
        this.write(b2);
    }
    
    final void writeEncodingDL(final boolean b, final int n, final byte[] array) throws IOException {
        this.writeIdentifier(b, n);
        this.writeDL(array.length);
        this.write(array, 0, array.length);
    }
    
    final void writeEncodingDL(final boolean b, final int n, final byte[] array, final int n2, final int n3) throws IOException {
        this.writeIdentifier(b, n);
        this.writeDL(n3);
        this.write(array, n2, n3);
    }
    
    final void writeEncodingDL(final boolean b, final int n, final byte b2, final byte[] array, final int n2, final int n3) throws IOException {
        this.writeIdentifier(b, n);
        this.writeDL(1 + n3);
        this.write(b2);
        this.write(array, n2, n3);
    }
    
    final void writeEncodingDL(final boolean b, final int n, final byte[] array, final int n2, final int n3, final byte b2) throws IOException {
        this.writeIdentifier(b, n);
        this.writeDL(n3 + 1);
        this.write(array, n2, n3);
        this.write(b2);
    }
    
    final void writeEncodingDL(final boolean b, final int n, final int n2, final byte[] array) throws IOException {
        this.writeIdentifier(b, n, n2);
        this.writeDL(array.length);
        this.write(array, 0, array.length);
    }
    
    final void writeEncodingIL(final boolean b, final int n, final ASN1Encodable[] array) throws IOException {
        this.writeIdentifier(b, n);
        this.write(128);
        this.writeElements(array);
        this.write(0);
        this.write(0);
    }
    
    final void writeIdentifier(final boolean b, final int n) throws IOException {
        if (b) {
            this.write(n);
        }
    }
    
    final void writeIdentifier(final boolean b, final int n, int i) throws IOException {
        if (b) {
            if (i < 31) {
                this.write(n | i);
            }
            else {
                final byte[] array = new byte[6];
                int length = array.length;
                array[--length] = (byte)(i & 0x7F);
                while (i > 127) {
                    i >>>= 7;
                    array[--length] = (byte)((i & 0x7F) | 0x80);
                }
                array[--length] = (byte)(n | 0x1F);
                this.write(array, length, array.length - length);
            }
        }
    }
    
    void writePrimitive(final ASN1Primitive asn1Primitive, final boolean b) throws IOException {
        asn1Primitive.encode(this, b);
    }
    
    void writePrimitives(final ASN1Primitive[] array) throws IOException {
        for (int i = 0; i < array.length; ++i) {
            array[i].encode(this, true);
        }
    }
    
    static int getLengthOfDL(int n) {
        if (n < 128) {
            return 1;
        }
        int n2 = 2;
        while ((n >>>= 8) != 0) {
            ++n2;
        }
        return n2;
    }
    
    static int getLengthOfEncodingDL(final boolean b, final int n) {
        return (b ? 1 : 0) + getLengthOfDL(n) + n;
    }
    
    static int getLengthOfIdentifier(int n) {
        if (n < 31) {
            return 1;
        }
        int n2 = 2;
        while ((n >>>= 7) != 0) {
            ++n2;
        }
        return n2;
    }
}
