HexEncoder.java revision e1142c149e244797ce73b0e7fad40816e447a817
1package org.bouncycastle.util.encoders;
2
3import java.io.IOException;
4import java.io.OutputStream;
5
6public class HexEncoder
7    implements Encoder
8{
9    protected final byte[] encodingTable =
10        {
11            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
12            (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
13        };
14
15    /*
16     * set up the decoding table.
17     */
18    protected final byte[] decodingTable = new byte[128];
19
20    protected void initialiseDecodingTable()
21    {
22        for (int i = 0; i < decodingTable.length; i++)
23        {
24            decodingTable[i] = (byte)0xff;
25        }
26
27        for (int i = 0; i < encodingTable.length; i++)
28        {
29            decodingTable[encodingTable[i]] = (byte)i;
30        }
31
32        decodingTable['A'] = decodingTable['a'];
33        decodingTable['B'] = decodingTable['b'];
34        decodingTable['C'] = decodingTable['c'];
35        decodingTable['D'] = decodingTable['d'];
36        decodingTable['E'] = decodingTable['e'];
37        decodingTable['F'] = decodingTable['f'];
38    }
39
40    public HexEncoder()
41    {
42        initialiseDecodingTable();
43    }
44
45    /**
46     * encode the input data producing a Hex output stream.
47     *
48     * @return the number of bytes produced.
49     */
50    public int encode(
51        byte[]                data,
52        int                    off,
53        int                    length,
54        OutputStream    out)
55        throws IOException
56    {
57        for (int i = off; i < (off + length); i++)
58        {
59            int    v = data[i] & 0xff;
60
61            out.write(encodingTable[(v >>> 4)]);
62            out.write(encodingTable[v & 0xf]);
63        }
64
65        return length * 2;
66    }
67
68    private static boolean ignore(
69        char    c)
70    {
71        return c == '\n' || c =='\r' || c == '\t' || c == ' ';
72    }
73
74    /**
75     * decode the Hex encoded byte data writing it to the given output stream,
76     * whitespace characters will be ignored.
77     *
78     * @return the number of bytes produced.
79     */
80    public int decode(
81        byte[]          data,
82        int             off,
83        int             length,
84        OutputStream    out)
85        throws IOException
86    {
87        byte    b1, b2;
88        int     outLen = 0;
89
90        int     end = off + length;
91
92        while (end > off)
93        {
94            if (!ignore((char)data[end - 1]))
95            {
96                break;
97            }
98
99            end--;
100        }
101
102        int i = off;
103        while (i < end)
104        {
105            while (i < end && ignore((char)data[i]))
106            {
107                i++;
108            }
109
110            b1 = decodingTable[data[i++]];
111
112            while (i < end && ignore((char)data[i]))
113            {
114                i++;
115            }
116
117            b2 = decodingTable[data[i++]];
118
119            if ((b1 | b2) < 0)
120            {
121                throw new IOException("invalid characters encountered in Hex data");
122            }
123
124            out.write((b1 << 4) | b2);
125
126            outLen++;
127        }
128
129        return outLen;
130    }
131
132    /**
133     * decode the Hex encoded String data writing it to the given output stream,
134     * whitespace characters will be ignored.
135     *
136     * @return the number of bytes produced.
137     */
138    public int decode(
139        String          data,
140        OutputStream    out)
141        throws IOException
142    {
143        byte    b1, b2;
144        int     length = 0;
145
146        int     end = data.length();
147
148        while (end > 0)
149        {
150            if (!ignore(data.charAt(end - 1)))
151            {
152                break;
153            }
154
155            end--;
156        }
157
158        int i = 0;
159        while (i < end)
160        {
161            while (i < end && ignore(data.charAt(i)))
162            {
163                i++;
164            }
165
166            b1 = decodingTable[data.charAt(i++)];
167
168            while (i < end && ignore(data.charAt(i)))
169            {
170                i++;
171            }
172
173            b2 = decodingTable[data.charAt(i++)];
174
175            if ((b1 | b2) < 0)
176            {
177                throw new IOException("invalid characters encountered in Hex string");
178            }
179
180            out.write((b1 << 4) | b2);
181
182            length++;
183        }
184
185        return length;
186    }
187}
188