001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.geronimo.util.encoders;
020
021 import java.io.IOException;
022 import java.io.OutputStream;
023
024 public class HexEncoder
025 implements Encoder
026 {
027 protected final byte[] encodingTable =
028 {
029 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
030 (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
031 };
032
033 /*
034 * set up the decoding table.
035 */
036 protected final byte[] decodingTable = new byte[128];
037
038 protected void initialiseDecodingTable()
039 {
040 for (int i = 0; i < encodingTable.length; i++)
041 {
042 decodingTable[encodingTable[i]] = (byte)i;
043 }
044
045 decodingTable['A'] = decodingTable['a'];
046 decodingTable['B'] = decodingTable['b'];
047 decodingTable['C'] = decodingTable['c'];
048 decodingTable['D'] = decodingTable['d'];
049 decodingTable['E'] = decodingTable['e'];
050 decodingTable['F'] = decodingTable['f'];
051 }
052
053 public HexEncoder()
054 {
055 initialiseDecodingTable();
056 }
057
058 /**
059 * encode the input data producing a Hex output stream.
060 *
061 * @return the number of bytes produced.
062 */
063 public int encode(
064 byte[] data,
065 int off,
066 int length,
067 OutputStream out)
068 throws IOException
069 {
070 for (int i = off; i < (off + length); i++)
071 {
072 int v = data[i] & 0xff;
073
074 out.write(encodingTable[(v >>> 4)]);
075 out.write(encodingTable[v & 0xf]);
076 }
077
078 return length * 2;
079 }
080
081 private boolean ignore(
082 char c)
083 {
084 return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
085 }
086
087 /**
088 * decode the Hex encoded byte data writing it to the given output stream,
089 * whitespace characters will be ignored.
090 *
091 * @return the number of bytes produced.
092 */
093 public int decode(
094 byte[] data,
095 int off,
096 int length,
097 OutputStream out)
098 throws IOException
099 {
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 }