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
029
030 /**
031 * Hex encoder and decoder.
032 *
033 * @since 1.1
034 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035 * @version $Id: Hex.java 664290 2008-06-07 06:28:06Z akarasulu $
036 */
037 public class Hex implements BinaryEncoder, BinaryDecoder
038 {
039
040 /**
041 * Used to build output as Hex
042 */
043 private static final char[] DIGITS =
044 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
045
046
047 /**
048 * Converts an array of characters representing hexidecimal values into an
049 * array of bytes of those same values. The returned array will be half the
050 * length of the passed array, as it takes two characters to represent any
051 * given byte. An exception is thrown if the passed char array has an odd
052 * number of elements.
053 *
054 * @param data
055 * An array of characters containing hexidecimal digits
056 * @return A byte array containing binary data decoded from the supplied
057 * char array.
058 * @throws DecoderException
059 * Thrown if an odd number or illegal of characters is supplied
060 */
061 public static byte[] decodeHex( char[] data ) throws DecoderException
062 {
063
064 int len = data.length;
065
066 if ( ( len & 0x01 ) != 0 )
067 {
068 throw new DecoderException( "Odd number of characters." );
069 }
070
071 byte[] out = new byte[len >> 1];
072
073 // two characters form the hex value.
074 for ( int i = 0, j = 0; j < len; i++ )
075 {
076 int f = toDigit( data[j], j ) << 4;
077 j++;
078 f |= toDigit( data[j], j );
079 j++;
080 out[i] = ( byte ) ( f & 0xFF );
081 }
082
083 return out;
084 }
085
086
087 /**
088 * Converts a hexadecimal character to an integer.
089 *
090 * @param ch
091 * A character to convert to an integer digit
092 * @param index
093 * The index of the character in the source
094 * @return An integer
095 * @throws DecoderException
096 * Thrown if ch is an illegal hex character
097 */
098 protected static int toDigit( char ch, int index ) throws DecoderException
099 {
100 int digit = Character.digit( ch, 16 );
101 if ( digit == -1 )
102 {
103 throw new DecoderException( "Illegal hexadecimal charcter " + ch + " at index " + index );
104 }
105 return digit;
106 }
107
108
109 /**
110 * Converts an array of bytes into an array of characters representing the
111 * hexidecimal values of each byte in order. The returned array will be
112 * double the length of the passed array, as it takes two characters to
113 * represent any given byte.
114 *
115 * @param data
116 * a byte[] to convert to Hex characters
117 * @return A char[] containing hexidecimal characters
118 */
119 public static char[] encodeHex( byte[] data )
120 {
121
122 int l = data.length;
123
124 char[] out = new char[l << 1];
125
126 // two characters form the hex value.
127 for ( int i = 0, j = 0; i < l; i++ )
128 {
129 out[j++] = DIGITS[( 0xF0 & data[i] ) >>> 4];
130 out[j++] = DIGITS[0x0F & data[i]];
131 }
132
133 return out;
134 }
135
136
137 /**
138 * Converts an array of character bytes representing hexidecimal values into
139 * an array of bytes of those same values. The returned array will be half
140 * the length of the passed array, as it takes two characters to represent
141 * any given byte. An exception is thrown if the passed char array has an
142 * odd number of elements.
143 *
144 * @param array
145 * An array of character bytes containing hexidecimal digits
146 * @return A byte array containing binary data decoded from the supplied
147 * byte array (representing characters).
148 * @throws DecoderException
149 * Thrown if an odd number of characters is supplied to this
150 * function
151 * @see #decodeHex(char[])
152 */
153 public byte[] decode( byte[] array ) throws DecoderException
154 {
155 return decodeHex( new String( array ).toCharArray() );
156 }
157
158
159 /**
160 * Converts a String or an array of character bytes representing hexidecimal
161 * values into an array of bytes of those same values. The returned array
162 * will be half the length of the passed String or array, as it takes two
163 * characters to represent any given byte. An exception is thrown if the
164 * passed char array has an odd number of elements.
165 *
166 * @param object
167 * A String or, an array of character bytes containing
168 * hexidecimal digits
169 * @return A byte array containing binary data decoded from the supplied
170 * byte array (representing characters).
171 * @throws DecoderException
172 * Thrown if an odd number of characters is supplied to this
173 * function or the object is not a String or char[]
174 * @see #decodeHex(char[])
175 */
176 public Object decode( Object object ) throws DecoderException
177 {
178 try
179 {
180 char[] charArray = object instanceof String ? ( ( String ) object ).toCharArray() : ( char[] ) object;
181 return decodeHex( charArray );
182 }
183 catch ( ClassCastException e )
184 {
185 throw new DecoderException( e.getMessage() );
186 }
187 }
188
189
190 /**
191 * Converts an array of bytes into an array of bytes for the characters
192 * representing the hexidecimal values of each byte in order. The returned
193 * array will be double the length of the passed array, as it takes two
194 * characters to represent any given byte.
195 *
196 * @param array
197 * a byte[] to convert to Hex characters
198 * @return A byte[] containing the bytes of the hexidecimal characters
199 * @see #encodeHex(byte[])
200 */
201 public byte[] encode( byte[] array )
202 {
203 return new String( encodeHex( array ) ).getBytes();
204 }
205
206
207 /**
208 * Converts a String or an array of bytes into an array of characters
209 * representing the hexidecimal values of each byte in order. The returned
210 * array will be double the length of the passed String or array, as it
211 * takes two characters to represent any given byte.
212 *
213 * @param object
214 * a String, or byte[] to convert to Hex characters
215 * @return A char[] containing hexidecimal characters
216 * @throws EncoderException
217 * Thrown if the given object is not a String or byte[]
218 * @see #encodeHex(byte[])
219 */
220 public Object encode( Object object ) throws EncoderException
221 {
222 try
223 {
224 byte[] byteArray = object instanceof String ? ( ( String ) object ).getBytes() : ( byte[] ) object;
225 return encodeHex( byteArray );
226 }
227 catch ( ClassCastException e )
228 {
229 throw new EncoderException( e.getMessage() );
230 }
231 }
232
233 }