1package org.bouncycastle.asn1;
2
3import java.io.IOException;
4
5/**
6 * DER NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
7 */
8public class DERNumericString
9    extends ASN1Object
10    implements DERString
11{
12    String  string;
13
14    /**
15     * return a Numeric string from the passed in object
16     *
17     * @exception IllegalArgumentException if the object cannot be converted.
18     */
19    public static DERNumericString getInstance(
20        Object  obj)
21    {
22        if (obj == null || obj instanceof DERNumericString)
23        {
24            return (DERNumericString)obj;
25        }
26
27        throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
28    }
29
30    /**
31     * return an Numeric String from a tagged object.
32     *
33     * @param obj the tagged object holding the object we want
34     * @param explicit true if the object is meant to be explicitly
35     *              tagged false otherwise.
36     * @exception IllegalArgumentException if the tagged object cannot
37     *               be converted.
38     */
39    public static DERNumericString getInstance(
40        ASN1TaggedObject obj,
41        boolean          explicit)
42    {
43        DERObject o = obj.getObject();
44
45        if (explicit || o instanceof DERNumericString)
46        {
47            return getInstance(o);
48        }
49        else
50        {
51            return new DERNumericString(ASN1OctetString.getInstance(o).getOctets());
52        }
53    }
54
55    /**
56     * basic constructor - with bytes.
57     */
58    public DERNumericString(
59        byte[]   string)
60    {
61        char[]  cs = new char[string.length];
62
63        for (int i = 0; i != cs.length; i++)
64        {
65            cs[i] = (char)(string[i] & 0xff);
66        }
67
68        this.string = new String(cs);
69    }
70
71    /**
72     * basic constructor -  without validation..
73     */
74    public DERNumericString(
75        String   string)
76    {
77        this(string, false);
78    }
79
80    /**
81     * Constructor with optional validation.
82     *
83     * @param string the base string to wrap.
84     * @param validate whether or not to check the string.
85     * @throws IllegalArgumentException if validate is true and the string
86     * contains characters that should not be in a NumericString.
87     */
88    public DERNumericString(
89        String   string,
90        boolean  validate)
91    {
92        if (validate && !isNumericString(string))
93        {
94            throw new IllegalArgumentException("string contains illegal characters");
95        }
96
97        this.string = string;
98    }
99
100    public String getString()
101    {
102        return string;
103    }
104
105    public String toString()
106    {
107        return string;
108    }
109
110    public byte[] getOctets()
111    {
112        char[]  cs = string.toCharArray();
113        byte[]  bs = new byte[cs.length];
114
115        for (int i = 0; i != cs.length; i++)
116        {
117            bs[i] = (byte)cs[i];
118        }
119
120        return bs;
121    }
122
123    void encode(
124        DEROutputStream  out)
125        throws IOException
126    {
127        out.writeEncoded(NUMERIC_STRING, this.getOctets());
128    }
129
130    public int hashCode()
131    {
132        return this.getString().hashCode();
133    }
134
135    boolean asn1Equals(
136        DERObject  o)
137    {
138        if (!(o instanceof DERNumericString))
139        {
140            return false;
141        }
142
143        DERNumericString  s = (DERNumericString)o;
144
145        return this.getString().equals(s.getString());
146    }
147
148    /**
149     * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
150     *
151     * @param str string to validate.
152     * @return true if numeric, fale otherwise.
153     */
154    public static boolean isNumericString(
155        String  str)
156    {
157        for (int i = str.length() - 1; i >= 0; i--)
158        {
159            char    ch = str.charAt(i);
160
161            if (ch > 0x007f)
162            {
163                return false;
164            }
165
166            if (('0' <= ch && ch <= '9') || ch == ' ')
167            {
168                continue;
169            }
170
171            return false;
172        }
173
174        return true;
175    }
176}
177