1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.geronimo.util.encoders;
20
21 import java.io.IOException;
22 import java.io.OutputStream;
23
24 public class HexEncoder
25 implements Encoder
26 {
27 protected final byte[] encodingTable =
28 {
29 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
30 (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
31 };
32
33
34
35
36 protected final byte[] decodingTable = new byte[128];
37
38 protected void initialiseDecodingTable()
39 {
40 for (int i = 0; i < encodingTable.length; i++)
41 {
42 decodingTable[encodingTable[i]] = (byte)i;
43 }
44
45 decodingTable['A'] = decodingTable['a'];
46 decodingTable['B'] = decodingTable['b'];
47 decodingTable['C'] = decodingTable['c'];
48 decodingTable['D'] = decodingTable['d'];
49 decodingTable['E'] = decodingTable['e'];
50 decodingTable['F'] = decodingTable['f'];
51 }
52
53 public HexEncoder()
54 {
55 initialiseDecodingTable();
56 }
57
58 /**
59 * encode the input data producing a Hex output stream.
60 *
61 * @return the number of bytes produced.
62 */
63 public int encode(
64 byte[] data,
65 int off,
66 int length,
67 OutputStream out)
68 throws IOException
69 {
70 for (int i = off; i < (off + length); i++)
71 {
72 int v = data[i] & 0xff;
73
74 out.write(encodingTable[(v >>> 4)]);
75 out.write(encodingTable[v & 0xf]);
76 }
77
78 return length * 2;
79 }
80
81 private boolean ignore(
82 char c)
83 {
84 return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
85 }
86
87 /**
88 * decode the Hex encoded byte data writing it to the given output stream,
89 * whitespace characters will be ignored.
90 *
91 * @return the number of bytes produced.
92 */
93 public int decode(
94 byte[] data,
95 int off,
96 int length,
97 OutputStream out)
98 throws IOException
99 {
100 byte[] bytes;
101 byte b1, b2;
102 int outLen = 0;
103
104 int end = off + length;
105
106 while (end > 0)
107 {
108 if (!ignore((char)data[end - 1]))
109 {
110 break;
111 }
112
113 end--;
114 }
115
116 int i = off;
117 while (i < end)
118 {
119 while (i < end && ignore((char)data[i]))
120 {
121 i++;
122 }
123
124 b1 = decodingTable[data[i++]];
125
126 while (i < end && ignore((char)data[i]))
127 {
128 i++;
129 }
130
131 b2 = decodingTable[data[i++]];
132
133 out.write((b1 << 4) | b2);
134
135 outLen++;
136 }
137
138 return outLen;
139 }
140
141 /**
142 * decode the Hex encoded String data writing it to the given output stream,
143 * whitespace characters will be ignored.
144 *
145 * @return the number of bytes produced.
146 */
147 public int decode(
148 String data,
149 OutputStream out)
150 throws IOException
151 {
152 byte[] bytes;
153 byte b1, b2, b3, b4;
154 int length = 0;
155
156 int end = data.length();
157
158 while (end > 0)
159 {
160 if (!ignore(data.charAt(end - 1)))
161 {
162 break;
163 }
164
165 end--;
166 }
167
168 int i = 0;
169 while (i < end)
170 {
171 while (i < end && ignore(data.charAt(i)))
172 {
173 i++;
174 }
175
176 b1 = decodingTable[data.charAt(i++)];
177
178 while (i < end && ignore(data.charAt(i)))
179 {
180 i++;
181 }
182
183 b2 = decodingTable[data.charAt(i++)];
184
185 out.write((b1 << 4) | b2);
186
187 length++;
188 }
189
190 return length;
191 }
192 }