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    }