001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with 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,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020
021 package org.apache.directory.shared.asn1.codec.binary;
022
023
024 import org.apache.directory.shared.asn1.codec.BinaryDecoder;
025 import org.apache.directory.shared.asn1.codec.BinaryEncoder;
026 import org.apache.directory.shared.asn1.codec.DecoderException;
027 import org.apache.directory.shared.asn1.codec.EncoderException;
028 import org.apache.directory.shared.i18n.I18n;
029
030
031 /**
032 * Hex encoder and decoder.
033 *
034 * @since 1.1
035 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
036 * @version $Id: Hex.java 912399 2010-02-21 20:52:31Z felixk $
037 */
038 public class Hex implements BinaryEncoder, BinaryDecoder
039 {
040
041 /**
042 * Used to build output as Hex
043 */
044 private static final char[] DIGITS =
045 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
046
047
048 /**
049 * Converts an array of characters representing hexidecimal values into an
050 * array of bytes of those same values. The returned array will be half the
051 * length of the passed array, as it takes two characters to represent any
052 * given byte. An exception is thrown if the passed char array has an odd
053 * number of elements.
054 *
055 * @param data
056 * An array of characters containing hexidecimal digits
057 * @return A byte array containing binary data decoded from the supplied
058 * char array.
059 * @throws DecoderException
060 * Thrown if an odd number or illegal of characters is supplied
061 */
062 public static byte[] decodeHex( char[] data ) throws DecoderException
063 {
064
065 int len = data.length;
066
067 if ( ( len & 0x01 ) != 0 )
068 {
069 throw new DecoderException( I18n.err( I18n.ERR_00013 ) );
070 }
071
072 byte[] out = new byte[len >> 1];
073
074 // two characters form the hex value.
075 for ( int i = 0, j = 0; j < len; i++ )
076 {
077 int f = toDigit( data[j], j ) << 4;
078 j++;
079 f |= toDigit( data[j], j );
080 j++;
081 out[i] = ( byte ) ( f & 0xFF );
082 }
083
084 return out;
085 }
086
087
088 /**
089 * Converts a hexadecimal character to an integer.
090 *
091 * @param ch
092 * A character to convert to an integer digit
093 * @param index
094 * The index of the character in the source
095 * @return An integer
096 * @throws DecoderException
097 * Thrown if ch is an illegal hex character
098 */
099 protected static int toDigit( char ch, int index ) throws DecoderException
100 {
101 int digit = Character.digit( ch, 16 );
102 if ( digit == -1 )
103 {
104 throw new DecoderException( I18n.err( I18n.ERR_00014, ch, index ) );
105 }
106 return digit;
107 }
108
109
110 /**
111 * Converts an array of bytes into an array of characters representing the
112 * hexidecimal values of each byte in order. The returned array will be
113 * double the length of the passed array, as it takes two characters to
114 * represent any given byte.
115 *
116 * @param data
117 * a byte[] to convert to Hex characters
118 * @return A char[] containing hexidecimal characters
119 */
120 public static char[] encodeHex( byte[] data )
121 {
122
123 int l = data.length;
124
125 char[] out = new char[l << 1];
126
127 // two characters form the hex value.
128 for ( int i = 0, j = 0; i < l; i++ )
129 {
130 out[j++] = DIGITS[( 0xF0 & data[i] ) >>> 4];
131 out[j++] = DIGITS[0x0F & data[i]];
132 }
133
134 return out;
135 }
136
137
138 /**
139 * Converts an array of character bytes representing hexidecimal values into
140 * an array of bytes of those same values. The returned array will be half
141 * the length of the passed array, as it takes two characters to represent
142 * any given byte. An exception is thrown if the passed char array has an
143 * odd number of elements.
144 *
145 * @param array
146 * An array of character bytes containing hexidecimal digits
147 * @return A byte array containing binary data decoded from the supplied
148 * byte array (representing characters).
149 * @throws DecoderException
150 * Thrown if an odd number of characters is supplied to this
151 * function
152 * @see #decodeHex(char[])
153 */
154 public byte[] decode( byte[] array ) throws DecoderException
155 {
156 return decodeHex( new String( array ).toCharArray() );
157 }
158
159
160 /**
161 * Converts a String or an array of character bytes representing hexidecimal
162 * values into an array of bytes of those same values. The returned array
163 * will be half the length of the passed String or array, as it takes two
164 * characters to represent any given byte. An exception is thrown if the
165 * passed char array has an odd number of elements.
166 *
167 * @param object
168 * A String or, an array of character bytes containing
169 * hexidecimal digits
170 * @return A byte array containing binary data decoded from the supplied
171 * byte array (representing characters).
172 * @throws DecoderException
173 * Thrown if an odd number of characters is supplied to this
174 * function or the object is not a String or char[]
175 * @see #decodeHex(char[])
176 */
177 public Object decode( Object object ) throws DecoderException
178 {
179 try
180 {
181 char[] charArray = object instanceof String ? ( ( String ) object ).toCharArray() : ( char[] ) object;
182 return decodeHex( charArray );
183 }
184 catch ( ClassCastException e )
185 {
186 throw new DecoderException( e.getMessage() );
187 }
188 }
189
190
191 /**
192 * Converts an array of bytes into an array of bytes for the characters
193 * representing the hexidecimal values of each byte in order. The returned
194 * array will be double the length of the passed array, as it takes two
195 * characters to represent any given byte.
196 *
197 * @param array
198 * a byte[] to convert to Hex characters
199 * @return A byte[] containing the bytes of the hexidecimal characters
200 * @see #encodeHex(byte[])
201 */
202 public byte[] encode( byte[] array )
203 {
204 return new String( encodeHex( array ) ).getBytes();
205 }
206
207
208 /**
209 * Converts a String or an array of bytes into an array of characters
210 * representing the hexidecimal values of each byte in order. The returned
211 * array will be double the length of the passed String or array, as it
212 * takes two characters to represent any given byte.
213 *
214 * @param object
215 * a String, or byte[] to convert to Hex characters
216 * @return A char[] containing hexidecimal characters
217 * @throws EncoderException
218 * Thrown if the given object is not a String or byte[]
219 * @see #encodeHex(byte[])
220 */
221 public Object encode( Object object ) throws EncoderException
222 {
223 try
224 {
225 byte[] byteArray = object instanceof String ? ( ( String ) object ).getBytes() : ( byte[] ) object;
226 return encodeHex( byteArray );
227 }
228 catch ( ClassCastException e )
229 {
230 throw new EncoderException( e.getMessage() );
231 }
232 }
233
234 }