/* You may freely copy, distribute, modify and use this class as long as the original author attribution remains intact. See message below. Copyright (C) 2003 Christian Pesch. All Rights Reserved. */ package slash.metamusic.hex; import java.io.IOException; import java.io.OutputStream; import java.io.Writer; /** * Helps to decode hexadecimally encoded digits to bytes, shorts, * ints or a hexadecimally encoded Writer to an OutputStream. * * @author Christian Pesch * @version $Id: HexDecoder.java 167 2003-12-08 11:41:43Z cpesch $ */ public class HexDecoder extends Writer { private OutputStream outputStream; public HexDecoder(OutputStream stream) { this.outputStream = stream; } public void write(String stringified, int from, int length) throws IOException { byte[] result = new byte[length / 2]; for (int i = 0; i < result.length; i++) { result[i] = (byte) ((decoding[stringified.charAt(from + 2 * i)] << 4) + decoding[stringified.charAt(from + 1 + 2 * i)]); } outputStream.write(result); } public void write(char[] stringified, int from, int length) throws IOException { write(new String(stringified), from, length); } public void flush() throws IOException { outputStream.flush(); } public void close() throws IOException { outputStream.close(); } /** * Decode the given string to a byte array. Requires, that the string is a * sequence of hex digits of even length. * * @param string the hex string to be decoded * @return the decoded bytes, where result[i] is computed from string.charAt(2*i) and string.charAt(2*i+1) * @see Character#digit */ public static byte[] decodeBytes(String string) { if (string.length() % 2 != 0) throw new IllegalArgumentException("Not an even number of hex digits: " + string); byte[] result = new byte[string.length() / 2]; for (int i = 0; i < result.length; ++i) { int highNibble = Character.digit(string.charAt(2 * i), 16); int lowNibble = Character.digit(string.charAt(2 * i + 1), 16); if (highNibble == -1 || lowNibble == -1) throw new IllegalArgumentException("Not a string of hex digits: " + string); result[i] = (byte) (highNibble * 16 + lowNibble); } return result; } private static byte[] decoding = new byte['g']; static { decoding['0'] = 0; decoding['1'] = 1; decoding['2'] = 2; decoding['3'] = 3; decoding['4'] = 4; decoding['5'] = 5; decoding['6'] = 6; decoding['7'] = 7; decoding['8'] = 8; decoding['9'] = 9; decoding['a'] = 10; decoding['b'] = 11; decoding['c'] = 12; decoding['d'] = 13; decoding['e'] = 14; decoding['f'] = 15; decoding['A'] = 10; decoding['B'] = 11; decoding['C'] = 12; decoding['D'] = 13; decoding['E'] = 14; decoding['F'] = 15; } public static byte decodeByte(String string, int pos) throws IndexOutOfBoundsException { return (byte) ((decoding[string.charAt(pos)] << 4) + decoding[string.charAt(pos + 1)]); } public static short decodeShort(String string, int pos) throws IndexOutOfBoundsException { return (short) ((decoding[string.charAt(pos)] << 12) + (decoding[string.charAt(pos + 1)] << 8) + (decoding[string.charAt(pos + 2)] << 4) + decoding[string.charAt(pos + 3)]); } public static int decodeInt(String string, int pos) throws IndexOutOfBoundsException { return ((decoding[string.charAt(pos)] << 28) + (decoding[string.charAt(pos + 1)] << 24) + (decoding[string.charAt(pos + 2)] << 20) + (decoding[string.charAt(pos + 3)] << 16) + (decoding[string.charAt(pos) + 4] << 12) + (decoding[string.charAt(pos + 5)] << 8) + (decoding[string.charAt(pos + 6)] << 4) + decoding[string.charAt(pos + 7)]); } }