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

package org.bouncycastle.asn1;

import java.io.IOException;
import org.bouncycastle.util.Arrays;

public abstract class ASN1BMPString extends ASN1Primitive implements ASN1String
{
    static final ASN1UniversalType TYPE;
    final char[] string;
    
    public static ASN1BMPString getInstance(final Object o) {
        if (o == null || o instanceof ASN1BMPString) {
            return (ASN1BMPString)o;
        }
        if (o instanceof ASN1Encodable) {
            final ASN1Primitive asn1Primitive = ((ASN1Encodable)o).toASN1Primitive();
            if (asn1Primitive instanceof ASN1BMPString) {
                return (ASN1BMPString)asn1Primitive;
            }
        }
        if (o instanceof byte[]) {
            try {
                return (ASN1BMPString)ASN1BMPString.TYPE.fromByteArray((byte[])o);
            }
            catch (final Exception ex) {
                throw new IllegalArgumentException("encoding error in getInstance: " + ex.toString());
            }
        }
        throw new IllegalArgumentException("illegal object in getInstance: " + o.getClass().getName());
    }
    
    public static ASN1BMPString getInstance(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        return (ASN1BMPString)ASN1BMPString.TYPE.getContextTagged(asn1TaggedObject, b);
    }
    
    public static ASN1BMPString getTagged(final ASN1TaggedObject asn1TaggedObject, final boolean b) {
        return (ASN1BMPString)ASN1BMPString.TYPE.getTagged(asn1TaggedObject, b);
    }
    
    ASN1BMPString(final String s) {
        if (s == null) {
            throw new NullPointerException("'string' cannot be null");
        }
        this.string = s.toCharArray();
    }
    
    ASN1BMPString(final byte[] array) {
        if (array == null) {
            throw new NullPointerException("'string' cannot be null");
        }
        final int length = array.length;
        if (0x0 != (length & 0x1)) {
            throw new IllegalArgumentException("malformed BMPString encoding encountered");
        }
        final int n = length / 2;
        final char[] string = new char[n];
        for (int i = 0; i != n; ++i) {
            string[i] = (char)(array[2 * i] << 8 | (array[2 * i + 1] & 0xFF));
        }
        this.string = string;
    }
    
    ASN1BMPString(final char[] string) {
        if (string == null) {
            throw new NullPointerException("'string' cannot be null");
        }
        this.string = string;
    }
    
    @Override
    public final String getString() {
        return new String(this.string);
    }
    
    @Override
    public String toString() {
        return this.getString();
    }
    
    @Override
    final boolean asn1Equals(final ASN1Primitive asn1Primitive) {
        return asn1Primitive instanceof ASN1BMPString && Arrays.areEqual(this.string, ((ASN1BMPString)asn1Primitive).string);
    }
    
    @Override
    public final int hashCode() {
        return Arrays.hashCode(this.string);
    }
    
    @Override
    final boolean encodeConstructed() {
        return false;
    }
    
    @Override
    final int encodedLength(final boolean b) {
        return ASN1OutputStream.getLengthOfEncodingDL(b, this.string.length * 2);
    }
    
    @Override
    final void encode(final ASN1OutputStream asn1OutputStream, final boolean b) throws IOException {
        final int length = this.string.length;
        asn1OutputStream.writeIdentifier(b, 30);
        asn1OutputStream.writeDL(length * 2);
        final byte[] array = new byte[8];
        int i = 0;
        while (i < (length & 0xFFFFFFFC)) {
            final char c = this.string[i];
            final char c2 = this.string[i + 1];
            final char c3 = this.string[i + 2];
            final char c4 = this.string[i + 3];
            i += 4;
            array[0] = (byte)(c >> 8);
            array[1] = (byte)c;
            array[2] = (byte)(c2 >> 8);
            array[3] = (byte)c2;
            array[4] = (byte)(c3 >> 8);
            array[5] = (byte)c3;
            array[6] = (byte)(c4 >> 8);
            array[7] = (byte)c4;
            asn1OutputStream.write(array, 0, 8);
        }
        if (i < length) {
            int n = 0;
            do {
                final char c5 = this.string[i];
                ++i;
                array[n++] = (byte)(c5 >> 8);
                array[n++] = (byte)c5;
            } while (i < length);
            asn1OutputStream.write(array, 0, n);
        }
    }
    
    static ASN1BMPString createPrimitive(final byte[] array) {
        return new DERBMPString(array);
    }
    
    static ASN1BMPString createPrimitive(final char[] array) {
        return new DERBMPString(array);
    }
    
    static {
        TYPE = new ASN1UniversalType(30) {
            @Override
            ASN1Primitive fromImplicitPrimitive(final DEROctetString derOctetString) {
                return ASN1BMPString.createPrimitive(derOctetString.getOctets());
            }
        };
    }
}
