1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Copyright 2001-2004 The Apache Software Foundation.
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * you may not use this file except in compliance with the License.
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * You may obtain a copy of the License at
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * See the License for the specific language governing permissions and
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * limitations under the License.
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.commons.codec.binary;
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.codec.BinaryDecoder;
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.codec.BinaryEncoder;
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.codec.DecoderException;
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.codec.EncoderException;
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Hex encoder and decoder.
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Apache Software Foundation
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Id: Hex.java,v 1.13 2004/04/18 18:22:33 ggregory Exp $
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class Hex implements BinaryEncoder, BinaryDecoder {
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Used building output as Hex
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final char[] DIGITS = {
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        '0', '1', '2', '3', '4', '5', '6', '7',
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    };
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts an array of characters representing hexidecimal values into an
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * array of bytes of those same values. The returned array will be half the
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * length of the passed array, as it takes two characters to represent any
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * given byte. An exception is thrown if the passed char array has an odd
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * number of elements.
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param data An array of characters containing hexidecimal digits
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return A byte array containing binary data decoded from
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         the supplied char array.
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws DecoderException Thrown if an odd number or illegal of characters
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         is supplied
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public static byte[] decodeHex(char[] data) throws DecoderException {
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int len = data.length;
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if ((len & 0x01) != 0) {
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new DecoderException("Odd number of characters.");
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        byte[] out = new byte[len >> 1];
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // two characters form the hex value.
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (int i = 0, j = 0; j < len; i++) {
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int f = toDigit(data[j], j) << 4;
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            j++;
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            f = f | toDigit(data[j], j);
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            j++;
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            out[i] = (byte) (f & 0xFF);
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return out;
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts a hexadecimal character to an integer.
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param ch A character to convert to an integer digit
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param index The index of the character in the source
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return An integer
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws DecoderException Thrown if ch is an illegal hex character
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected static int toDigit(char ch, int index) throws DecoderException {
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int digit = Character.digit(ch, 16);
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (digit == -1) {
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new DecoderException("Illegal hexadecimal charcter " + ch + " at index " + index);
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return digit;
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts an array of bytes into an array of characters representing the hexidecimal values of each byte in order.
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The returned array will be double the length of the passed array, as it takes two characters to represent any
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * given byte.
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param data
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                  a byte[] to convert to Hex characters
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return A char[] containing hexidecimal characters
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public static char[] encodeHex(byte[] data) {
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int l = data.length;
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           char[] out = new char[l << 1];
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           // two characters form the hex value.
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           for (int i = 0, j = 0; i < l; i++) {
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project               out[j++] = DIGITS[(0xF0 & data[i]) >>> 4 ];
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project               out[j++] = DIGITS[ 0x0F & data[i] ];
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           }
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project           return out;
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts an array of character bytes representing hexidecimal values into an
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * array of bytes of those same values. The returned array will be half the
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * length of the passed array, as it takes two characters to represent any
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * given byte. An exception is thrown if the passed char array has an odd
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * number of elements.
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param array An array of character bytes containing hexidecimal digits
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return A byte array containing binary data decoded from
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         the supplied byte array (representing characters).
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws DecoderException Thrown if an odd number of characters is supplied
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                   to this function
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @see #decodeHex(char[])
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public byte[] decode(byte[] array) throws DecoderException {
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return decodeHex(new String(array).toCharArray());
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts a String or an array of character bytes representing hexidecimal values into an
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * array of bytes of those same values. The returned array will be half the
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * length of the passed String or array, as it takes two characters to represent any
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * given byte. An exception is thrown if the passed char array has an odd
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * number of elements.
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param object A String or, an array of character bytes containing hexidecimal digits
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return A byte array containing binary data decoded from
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *         the supplied byte array (representing characters).
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws DecoderException Thrown if an odd number of characters is supplied
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *                   to this function or the object is not a String or char[]
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @see #decodeHex(char[])
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Object decode(Object object) throws DecoderException {
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char[] charArray = object instanceof String ? ((String) object).toCharArray() : (char[]) object;
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return decodeHex(charArray);
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch (ClassCastException e) {
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new DecoderException(e.getMessage());
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts an array of bytes into an array of bytes for the characters representing the
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * hexidecimal values of each byte in order. The returned array will be
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * double the length of the passed array, as it takes two characters to
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * represent any given byte.
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param array a byte[] to convert to Hex characters
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return A byte[] containing the bytes of the hexidecimal characters
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @see #encodeHex(byte[])
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public byte[] encode(byte[] array) {
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return new String(encodeHex(array)).getBytes();
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Converts a String or an array of bytes into an array of characters representing the
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * hexidecimal values of each byte in order. The returned array will be
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * double the length of the passed String or array, as it takes two characters to
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * represent any given byte.
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param object a String, or byte[] to convert to Hex characters
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return A char[] containing hexidecimal characters
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws EncoderException Thrown if the given object is not a String or byte[]
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @see #encodeHex(byte[])
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Object encode(Object object) throws EncoderException {
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        try {
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            byte[] byteArray = object instanceof String ? ((String) object).getBytes() : (byte[]) object;
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return encodeHex(byteArray);
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } catch (ClassCastException e) {
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new EncoderException(e.getMessage());
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
193