blob: 510ae1ce75216e5dc6445b7df903a9bb7312b946 [file] [log] [blame]
/*
* Copyright (c) 2007, 2009-2012 Eike Stepper (Berlin, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.util;
import org.eclipse.net4j.util.io.IORuntimeException;
import java.io.IOException;
/**
* Provides static methods that convert to and from hexadecimal string formats.
*
* @author Eike Stepper
*/
public final class HexUtil
{
public static final char DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e',
'f', };
private HexUtil()
{
}
/**
* Converts a byte array into a string of lower 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)
{
if (bs == null)
{
return null;
}
if (bs.length <= off || bs.length < off + length)
{
throw new IllegalArgumentException();
}
StringBuilder sb = new StringBuilder(length * 2);
bytesToHexAppend(bs, off, length, sb);
return sb.toString();
}
public static void bytesToHexAppend(byte[] bs, int off, int length, Appendable appendable)
{
if (bs.length <= off || bs.length < off + length)
{
throw new IllegalArgumentException();
}
if (appendable instanceof StringBuffer)
{
StringBuffer buffer = (StringBuffer)appendable;
buffer.ensureCapacity(buffer.length() + length * 2);
}
try
{
for (int i = off; i < off + length; i++)
{
appendable.append(Character.forDigit(bs[i] >>> 4 & 0xf, 16));
appendable.append(Character.forDigit(bs[i] & 0xf, 16));
}
}
catch (IOException ex)
{
throw new IORuntimeException(ex);
}
}
public static String bytesToHex(byte[] bs)
{
if (bs == null)
{
return null;
}
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();
if ((slen & 1) == 1)
{
s = '0' + s;
}
if (out.length < off + (slen >> 1))
{
throw new IndexOutOfBoundsException("Output buffer too small for input (" + out.length + '<' + off + (slen >> 1) //$NON-NLS-1$
+ ')');
}
// Safe to assume the string is even length
byte b1, b2;
for (int i = 0; i < slen; i += 2)
{
b1 = (byte)Character.digit(s.charAt(i), 16);
b2 = (byte)Character.digit(s.charAt(i + 1), 16);
if (b1 < 0 || b2 < 0)
{
throw new NumberFormatException(s);
}
out[off + i / 2] = (byte)(b1 << 4 | b2);
}
}
public static String longToHex(long v)
{
final String hex = Long.toHexString(v);
if (hex.length() < 8)
{
return "00000000".substring(hex.length()) + hex; //$NON-NLS-1$
}
return hex;
}
@Deprecated
public static String formatByte(int b)
{
assertByte(b);
return "" + DIGITS[b >> 4] + DIGITS[b & 0xf]; //$NON-NLS-1$
}
@Deprecated
public static String formatBytes(byte[] bytes)
{
StringBuilder builder = new StringBuilder();
for (byte b : bytes)
{
appendHex(builder, b - Byte.MIN_VALUE);
}
return builder.toString();
}
@Deprecated
public static void appendHex(StringBuilder builder, int b)
{
assertByte(b);
builder.append(DIGITS[b >> 4]);
builder.append(DIGITS[b & 0xf]);
}
@Deprecated
private static void assertByte(int b)
{
if (b < 0 || b > 255)
{
throw new IllegalArgumentException("b=" + b); //$NON-NLS-1$
}
}
}