/*
* Copyright (c) 2016 OBiBa. All rights reserved.
*
* This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.obiba.core.util;
/**
* Copied from http://www.koders.com/java/fid03708253E2C24FCEF72C90AE2948739B84F7026F.aspx
*/
@SuppressWarnings({ "UnusedDeclaration", "MagicNumber" })
final public class HexUtil {
private HexUtil() {
}
/**
* Converts a byte array into a string of upper case hex chars.
*
* @param bs A byte array
* @param off The index of the first byte to read
* @param length The number of bytes to read.
* @return the string of hex chars.
*/
public static String bytesToHex(byte[] bs, int off, int length) {
StringBuffer sb = new StringBuffer(length * 2);
bytesToHexAppend(bs, off, length, sb);
return sb.toString();
}
public static void bytesToHexAppend(byte[] bs, int off, int length, StringBuffer sb) {
sb.ensureCapacity(sb.length() + length * 2);
for(int i = off; i < off + length && i < bs.length; i++) {
sb.append(Character.forDigit(bs[i] >>> 4 & 0xf, 16));
sb.append(Character.forDigit(bs[i] & 0xf, 16));
}
}
public static String bytesToHex(byte... bs) {
return bytesToHex(bs, 0, bs.length);
}
public static byte[] hexToBytes(String s) {
return hexToBytes(s, 0);
}
public static byte[] hexToBytes(String s, int off) {
byte[] bs = new byte[off + (1 + s.length()) / 2];
hexToBytes(s, bs, off);
return bs;
}
/**
* Converts a String of hex characters into an array of bytes.
*
* @param s A string of hex characters (upper case or lower) of even length.
* @param out A byte array of length at least s.length()/2 + off
* @param off The first byte to write of the array
*/
public static void hexToBytes(String s, byte[] out, int off) throws NumberFormatException, IndexOutOfBoundsException {
int slen = s.length();
String filledString = s;
if(slen % 2 != 0) {
filledString = '0' + s;
}
if(out.length < off + slen / 2) {
throw new IndexOutOfBoundsException(
"Output buffer too small for input (" + out.length + "<" + (off + slen / 2) + ")");
}
// Safe to assume the string is even length
byte b1, b2;
for(int i = 0; i < slen; i += 2) {
b1 = (byte) Character.digit(filledString.charAt(i), 16);
b2 = (byte) Character.digit(filledString.charAt(i + 1), 16);
if(b1 < 0 || b2 < 0) {
throw new NumberFormatException();
}
out[off + i / 2] = (byte) (b1 << 4 | b2);
}
}
}