1package org.bouncycastle.asn1;
2
3import java.io.IOException;
4
5/**
6 * A Definite length BIT STRING
7 */
8public class DLBitString
9    extends ASN1BitString
10{
11    /**
12     * return a Bit String that can be definite-length encoded from the passed in object.
13     *
14     * @param obj a DL or DER BitString or an object that can be converted into one.
15     * @exception IllegalArgumentException if the object cannot be converted.
16     * @return an ASN1BitString instance, or null.
17     */
18    public static ASN1BitString getInstance(
19        Object  obj)
20    {
21        if (obj == null || obj instanceof DLBitString)
22        {
23            return (DLBitString)obj;
24        }
25        if (obj instanceof DERBitString)
26        {
27            return (DERBitString)obj;
28        }
29
30        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
31    }
32
33    /**
34     * return a Bit String from a tagged object.
35     *
36     * @param obj the tagged object holding the object we want
37     * @param explicit true if the object is meant to be explicitly
38     *              tagged false otherwise.
39     * @exception IllegalArgumentException if the tagged object cannot
40     *               be converted.
41     * @return an ASN1BitString instance, or null.
42     */
43    public static ASN1BitString getInstance(
44        ASN1TaggedObject obj,
45        boolean          explicit)
46    {
47        ASN1Primitive o = obj.getObject();
48
49        if (explicit || o instanceof DLBitString)
50        {
51            return getInstance(o);
52        }
53        else
54        {
55            return fromOctetString(((ASN1OctetString)o).getOctets());
56        }
57    }
58
59    protected DLBitString(
60        byte    data,
61        int     padBits)
62    {
63        this(toByteArray(data), padBits);
64    }
65
66    private static byte[] toByteArray(byte data)
67    {
68        byte[] rv = new byte[1];
69
70        rv[0] = data;
71
72        return rv;
73    }
74
75    /**
76     * @param data the octets making up the bit string.
77     * @param padBits the number of extra bits at the end of the string.
78     */
79    public DLBitString(
80        byte[]  data,
81        int     padBits)
82    {
83        super(data, padBits);
84    }
85
86    public DLBitString(
87        byte[]  data)
88    {
89        this(data, 0);
90    }
91
92    public DLBitString(
93        int value)
94    {
95        super(getBytes(value), getPadBits(value));
96    }
97
98    public DLBitString(
99        ASN1Encodable obj)
100        throws IOException
101    {
102        super(obj.toASN1Primitive().getEncoded(ASN1Encoding.DER), 0);
103    }
104
105    boolean isConstructed()
106    {
107        return false;
108    }
109
110    int encodedLength()
111    {
112        return 1 + StreamUtil.calculateBodyLength(data.length + 1) + data.length + 1;
113    }
114
115    void encode(
116        ASN1OutputStream  out)
117        throws IOException
118    {
119        byte[] string = data;
120        byte[] bytes = new byte[string.length + 1];
121
122        bytes[0] = (byte)getPadBits();
123        System.arraycopy(string, 0, bytes, 1, bytes.length - 1);
124
125        out.writeEncoded(BERTags.BIT_STRING, bytes);
126    }
127
128    static DLBitString fromOctetString(byte[] bytes)
129    {
130        if (bytes.length < 1)
131        {
132            throw new IllegalArgumentException("truncated BIT STRING detected");
133        }
134
135        int padBits = bytes[0];
136        byte[] data = new byte[bytes.length - 1];
137
138        if (data.length != 0)
139        {
140            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
141        }
142
143        return new DLBitString(data, padBits);
144    }
145}
146