/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you under the Apache License, Version 2.0 (the | |
* "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, | |
* software distributed under the License is distributed on an | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
* KIND, either express or implied. See the License for the | |
* specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package org.apache.myfaces.util.lang; | |
// minimal version of org.apache.commons.codec.binary.Hex to avoid commons-codec or JAXB DatatypeConverter dependency. | |
public class Hex | |
{ | |
/** | |
* Used to build output as Hex | |
*/ | |
private static final char[] DIGITS_LOWER | |
= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; | |
/** | |
* Used to build output as Hex | |
*/ | |
private static final char[] DIGITS_UPPER | |
= {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; | |
/** | |
* Converts a String representing hexadecimal values into an array of bytes of those same values. The | |
* returned array will be half the length of the passed String, as it takes two characters to represent any given | |
* byte. An exception is thrown if the passed String has an odd number of elements. | |
* | |
* @param data | |
* A String containing hexadecimal digits | |
* | |
* @return A byte array containing binary data decoded from the supplied char array. | |
* | |
* @throws IllegalArgumentException | |
* Thrown if an odd number or illegal of characters is supplied | |
* @since 1.11 | |
*/ | |
public static byte[] decodeHex(final String data) throws IllegalArgumentException | |
{ | |
return decodeHex(data.toCharArray()); | |
} | |
/** | |
* Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The | |
* returned array will be half the length of the passed array, as it takes two characters to represent any given | |
* byte. An exception is thrown if the passed char array has an odd number of elements. | |
* | |
* @param data | |
* An array of characters containing hexadecimal digits | |
* | |
* @return A byte array containing binary data decoded from the supplied char array. | |
* | |
* @throws IllegalArgumentException | |
* Thrown if an odd number or illegal of characters is supplied | |
*/ | |
public static byte[] decodeHex(final char[] data) throws IllegalArgumentException | |
{ | |
final int len = data.length; | |
if ((len & 0x01) != 0) | |
{ | |
throw new IllegalArgumentException("Odd number of characters."); | |
} | |
final byte[] out = new byte[len >> 1]; | |
// two characters form the hex value. | |
for (int i = 0, j = 0; j < len; i++) | |
{ | |
int f = toDigit(data[j], j) << 4; | |
j++; | |
f = f | toDigit(data[j], j); | |
j++; | |
out[i] = (byte) (f & 0xFF); | |
} | |
return out; | |
} | |
/** | |
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. | |
* The returned array will be double the length of the passed array, as it takes two characters to represent any | |
* given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* | |
* @return A char[] containing lower-case hexadecimal characters | |
*/ | |
public static char[] encodeHex(final byte[] data) | |
{ | |
return encodeHex(data, true); | |
} | |
/** | |
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. | |
* The returned array will be double the length of the passed array, as it takes two characters to represent any | |
* given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* @param toLowerCase | |
* <code>true</code> converts to lowercase, <code>false</code> to uppercase | |
* | |
* @return A char[] containing hexadecimal characters in the selected case | |
* | |
* @since 1.4 | |
*/ | |
public static char[] encodeHex(final byte[] data, final boolean toLowerCase) | |
{ | |
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER); | |
} | |
/** | |
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order. | |
* The returned array will be double the length of the passed array, as it takes two characters to represent any | |
* given byte. | |
* | |
* @param data | |
* a byte[] to convert to Hex characters | |
* @param toDigits | |
* the output alphabet (must contain at least 16 chars) | |
* | |
* @return A char[] containing the appropriate characters from the alphabet | |
* For best results, this should be either upper- or lower-case hex. | |
* | |
* @since 1.4 | |
*/ | |
protected static char[] encodeHex(final byte[] data, final char[] toDigits) | |
{ | |
final int l = data.length; | |
final char[] out = new char[l << 1]; | |
// two characters form the hex value. | |
for (int i = 0, j = 0; i < l; i++) | |
{ | |
out[j++] = toDigits[(0xF0 & data[i]) >>> 4]; | |
out[j++] = toDigits[0x0F & data[i]]; | |
} | |
return out; | |
} | |
/** | |
* Converts a hexadecimal character to an integer. | |
* | |
* @param ch | |
* A character to convert to an integer digit | |
* @param index | |
* The index of the character in the source | |
* | |
* @return An integer | |
* | |
* @throws IllegalArgumentException | |
* Thrown if ch is an illegal hex character | |
*/ | |
protected static int toDigit(final char ch, final int index) throws IllegalArgumentException | |
{ | |
final int digit = Character.digit(ch, 16); | |
if (digit == -1) | |
{ | |
throw new IllegalArgumentException("Illegal hexadecimal character " + ch + " at index " + index); | |
} | |
return digit; | |
} | |
} |